Dieser Artikel stellt Ihnen vor allem vor, wie Vue3 ein globales Suchfeld implementiert. Ich hoffe, es wird Ihnen helfen helfen.
Vorwort: Seit ich Vue kennengelernt habe, bin ich besessen von der globalen Funktion Befehl + K der offiziellen Vue-Website, um die globale Stichwortsuche aufzurufen. Zufälligerweise muss ein aktuelles Projekt auch eine globale Suchfunktion implementieren, und zufällig kann ich die Idee dieser Funktion mit Bezahlung lernen. Das Niveau der Tutorials im Internet ist ungleichmäßig, und ich habe in einem früheren Projekt zufällig eine Funktion ähnlich den globalen Popup-Breadcrumbs ausgeführt, also habe ich Schlussfolgerungen gezogen und ein globales Suchfeld geschrieben, das unser Projekt benötigt, und das würde ich gerne tun teile meine Ideen.
Hinweis: In diesem Artikel lernen Sie nicht sofort, wie Sie Code schreiben, sondern dienen als Leitfaden, der Sie Schritt für Schritt dabei unterstützt, die Designideen dieser Komponente zu verstehen. Es wird aus der Perspektive erklärt: „Wenn ich ein Anfänger bin und mir das jemand sagen kann, wenn ich dieses Wissen lerne, dann kann ich es schnell verstehen“, Es ist besser, einer Person einen Fisch beizubringen, als es zu tun Bringe ihm das Fischen bei . Ich hoffe, dass Sie beim Lesen dieses Artikels Ihr Denken erweitern und Schlussfolgerungen ziehen können. ?? Forschung. ts
Datei2. Der Stil des Suchfelds Das Thema Stil steht nicht im Mittelpunkt dieses Artikels. Sie können fünf Minuten damit verbringen, ein sehr einfaches quadratisches
divSearchBar.vue-Eingabetag, um schnell mit dem folgenden Lernen fortzufahren.
SearchBar.vue
, um einen Stil für das äußerste div
festzulegen. Die anderen Stile hier werden mit Uno CSS
geschrieben, was nutzlos ist. Freunde, die es erlebt haben, brauchen sich keine Sorgen zu machen, es ist nur ein einfacher Stil und hat nichts mit dem zentralen Inhalt dieses Artikels zu tun. (CSS, das als berechnete Eigenschaften geschrieben wird, hat in diesem Szenario keine besondere Bedeutung, wird beim Entwurf jedoch einfach stärker berücksichtigt.) .png" alt="Detaillierte grafische Erläuterung der Schritte zur Implementierung des globalen Suchfelds in Vue3 (mit Code)" Loading="lazy"/>h und render
-Funktion (wichtiger Punkt)Öffnen Sie die zuvor vorbereitete
SearchBar.tsund führen Sie die einfache Version des darin geschriebenen Suchfelds (SearchBar.vue) ein vorherigen Schritt in diese Datei. Schau Sehen Sie sich meinen vorherigen Artikel an " >Leser, die einen Toast in Vue3 implementieren, sind vielleicht ein wenig damit vertraut, aber in diesem Artikel kam ich zum ersten Mal mit diesen beiden Funktionen in Berührung, sodass die Zusammenfassung zu diesem Zeitpunkt nicht besonders genau war , also habe ich meine Ideen noch einmal präzisiert. Lassen Sie es uns hier noch einmal erklären.
Werfen wir zunächst einen Blick auf die Definition dieser Funktion aus der Einleitung auf der offiziellen Website.
Ja Es ist ersichtlich, dass der erste Parameter dieser Funktion erforderlich ist und ein string
und eine Component
sein kann. Dieser Artikel konzentriert sich auf die Parameter-Component
-Situation . Der Punkt ist, dass der Rückgabewert dieser Funktion ein VNode
ist, mit dem Sie vertraut sein müssen, SearchBar.vue
去设置一个样式给最外层的 div
,这里其它样式的写法使用的是 Uno CSS
,没用过的小伙伴也不需要担心,它只是单纯的样式,和本文中心内容不牵扯。(CSS写成计算属性在这个场景也毫无特殊意义,只是单纯设计时考虑多了)
打开之前准备的 SearchBar.ts 文件,从 vue 里引入这两个函数,并且把在上一步写好的简陋版搜索框(SearchBar.vue)引入到这个文件内。
看过我之前文章 Vue3实现一个 Toast 的读者可能会比较熟悉一点点,但是在那一篇文章内由于我也是初次接触这两个函数,所以当时总结的也不是特别精确,所以重新捋清思路,这里再讲解一下。
首先我们从官网的介绍,先看一下这个函数的定义。
可以看出,这个函数第一个参数是必填的,可以是一个 string
和 Component
,这篇文章重点讨论参数为 Component
的情况。重点是这个函数的返回值,是一个 VNode
Virtual Node. Den Lesern dieses Artikels ist das Prinzip des virtuellen dom möglicherweise nicht so klar , aber ich glaube, Sie müssen den grundlegenden Mechanismus kennen. Vue rendert tatsächlich zuerst den virtuellen Dom -> und wandelt ihn dann in einen echten Dom um.
Beeilen Sie sich nicht, den Code zu schreiben. Ich denke, Sie kennen diese Schreibweise vielleicht besser, wie zum Beispiel das einfache Popup-Fenster, das wir in der Datei SearchBar.vue geschrieben haben. Der Stil der gesamten Komponente wird in der von Vue bereitgestellten -Komponente geschrieben, Sie müssen jedoch wissen, dass Vue den Aufbau des virtuellen dom durch den Aufruf von h() noch abschließt ganz unten . Und ist lediglich syntaktischer Zucker, der von Vue bereitgestellt wird, damit Sie mit dem vertrauten nativen HTML entwickeln können. (Nun, Sie können es so verstehen)
Dann können wir der Einführung der Funktion h() oben folgen. Der erste Parameter, den sie empfängt, kann Component
sein, dann unser SearchBar Ist .vue
nicht nur eine Komponente? Wenn ich also Component
,那我们这个 SearchBar.vue
不就是组件吗?那如果我不想使用 去展示这个组件的话,我是否可以这样写呢?h(SearchBar.vue)
。没错,是的,你就是可以这样写。别忘了 h
的返回值就是我们想拿到的 Vnode ,所以按照正确的写法是这样的。
让我们回到 SearchBar.ts
文件。
首先思考,这个搜索框一定有一个出现的函数,和一个消失的函数?,ok,起名字,一个 present,一个 dismiss 。
接下来我需要创建出一个 VNode ,然后想办法处理成真实 dom。经过上面的学习,第一步马上就可以想到下面的写法。
下面这位更是重量级,render()
函数。虚拟 dom 有了,真实dom 该如何拿到呢? Vue 为我们提供了这样一个函数,这里我们需要重点去看这个函数的类型是值,是一个 RootRenderFunction
类型的。
这里我们转变一下思路,我们看一下 render 函数的第二个参数是 一个 container:HostElement ,然后让我们打开我们 main.ts 文件,我们跳进 mount
的定义部分,发现神奇的地方了吗,我们虽然不知道 HostElement 的类型是什么,但是你知道你 mount
函数内填的参数是什么了吗?(忘掉的转头自觉复习官网哈。)
没错,就是全局唯一的一个真实 dom,一个朴实无华的id叫 app
nicht zum Anzeigen dieser Komponente verwenden möchte, kann ich sie dann so schreiben? h(SearchBar.vue)
. Ja, ja, man kann es so schreiben. Vergessen Sie nicht, dass der Rückgabewert von h
der Vnode ist, den wir erhalten möchten. Die richtige Schreibweise sieht also so aus.
SearchBar.ts
. 🎜Zuerst Denken Sie darüber nach, dieses Suchfeld muss eine Funktion zum Erscheinen und eine Funktion zum Verschwinden haben? Ok, geben wir ihm einen Namen, einen „präsent“ und einen „verwerfen“. render()
. Jetzt, wo wir ein virtuelles Domizil haben, wie können wir ein reales Domizil bekommen? 🎜Vue🎜 stellt uns eine solche Funktion zur Verfügung. Hier müssen wir uns darauf konzentrieren, dass der Typ dieser Funktion ein Wert ist, der ein RootRenderFunction
-Typ ist. 🎜🎜🎜🎜hier Lassen Sie uns unsere Denkweise ändern und sehen, dass der zweite Parameter der 🎜render🎜-Funktion ein 🎜container:HostElement🎜 ist. Dann öffnen wir unsere 🎜main.ts🎜-Datei und springen in die Definition des mount
-Teils , Haben Sie einen magischen Ort entdeckt? Ich weiß nicht, was der Typ von 🎜HostElement🎜 ist. Wissen Sie, welche Parameter in Ihrer mount
-Funktion ausgefüllt sind? (Wenn ich es vergessen habe, habe ich mich umgedreht und die offizielle Website bewusst überprüft.)app Code>. 🎜Aufgrund von Platzbeschränkungen können Sie hier zunächst kurz verstehen, dass die 🎜render🎜-Funktion Ihr virtuelles 🎜dom🎜 in ein echtes 🎜dom🎜-Element verpackt, aber Sie müssen ihm ein echtes 🎜Shell-Dom🎜 geben, um zu sagen, wo es gerendert wird das virtuelle 🎜dom🎜 zu. 🎜<li><p>OK, nachdem Sie einen gepackten virtuellen Dom erhalten haben, besteht der nächste Schritt darin, dem Browser mitzuteilen, wo dieses Element gerendert werden soll. Hier müssen wir bedenken, dass es auf allen Komponenten angezeigt werden muss, da es global angezeigt werden kann. <img src="https://img.php.cn/upload/article/000/000/020/2684ad00bc24159a077a8a166c9d8d3b-16.png" alt="Detaillierte grafische Erläuterung der Schritte zur Implementierung des globalen Suchfelds in Vue3 (mit Code)" loading="lazy">Am einfachsten ist es, es im ersten Element von <strong>body</strong> erscheinen zu lassen, dann befindet es sich auf der gleichen Ebene wie alle Komponenten unserer Webseite (Tipps: Normalerweise werden alle unsere Seitenkomponenten in einem der <strong> geschrieben body</strong> <strong>div</strong> Was? Sie fragen mich warum? Bitte öffnen Sie Ihre <strong>index.html</strong> und sehen Sie, ob Sie vergessen haben, dass unser <strong>App.vue</strong> in diesem echten Element mit <strong>id app</strong> hängt Unsere Bedienung ist sehr einfach. Wenn ich die globale Suchschaltfläche drücke, fügen Sie mein Element vor den <code><div id="app">-Komponenten ein. <img src="https://img.php.cn/upload/article/000/000/020/659e9d144b30400682dc69d8bf2b853c-18.png" alt="Detaillierte grafische Erläuterung der Schritte zur Implementierung des globalen Suchfelds in Vue3 (mit Code)" loading="lazy"><img src="https://img.php.cn/upload/article/000/000/020/659e9d144b30400682dc69d8bf2b853c-17.png" alt="Detaillierte grafische Erläuterung der Schritte zur Implementierung des globalen Suchfelds in Vue3 (mit Code)" loading="lazy"><code><div id="app"> 的元素之前插入我的组件即可。<img src="https://img.php.cn/upload/article/000/000/020/659e9d144b30400682dc69d8bf2b853c-18.png" alt="Detaillierte grafische Erläuterung der Schritte zur Implementierung des globalen Suchfelds in Vue3 (mit Code)" loading="lazy"><li><p>ok,到这里我们已经可以看到基本效果了,我们来测试一下。让我们在 <code>App.vue
组件内随便写一个按钮,然后调用 SearchBarCreator
实例身上的 present
方法。(maker 感觉不是那么合理,之后我们将 SearchBarMaker
变更为 SeachBarCreator
的叫法,仅仅是名字变了而已,逻辑什么的根本没变哦。?)效果如下:到这里 searchBar 已经可以呈现在页面上了,但是我们还不知道怎样让它消失,其实也非常简单,我们只需要在合适的时机移除这个 dom 元素即可。在这里我们需要知道一点,我们需要将 searchBar
提升到当前文件的全局,不能仅只在 open
中去 new
了。
ok,我们测试一下
写到这里的时候,你可能发现了一个小问题,当我一直去按搜索按钮的时候,它会出现多个搜索框,但是我们希望的是它在全局只能出现一个搜索框。换个角度思考,也就是同一时间,这个被我们 new
出来的 SeachBar
实例只能出现一个。思考一下?,我加一个变量,isShowing 是否正在被展示
,如果正在被展示的话,那么用户再次调用 present
的时候,我就去调用实例自身的 dismiss
方法让它消失,是否可行呢?
测试一下:
OK,看来完美解决当前的问题了。
在上面的这种情况下,我们已经可以在 App.vue
文件内去 new
一个实例来调用这个搜索框了。但是我们加入现在需要在 XXX.vue
文件内调用这个搜索框呢?我难道还需要重新去引入,然后重新 new
App.vue
und rufen Sie dann die Methode present
für die Instanz SearchBarCreator
auf. (🎜maker🎜 Es fühlt sich nicht so vernünftig an. Später haben wir den Namen von SearchBarMaker
in SeachBarCreator
geändert. Nur der Name hat sich geändert, und die Logik hat sich überhaupt nicht geändert .? )Der Effekt lautet wie folgt:🎜🎜🎜🎜Here🎜searchBar🎜 kann auf der Seite angezeigt werden, aber wir wissen noch nicht, wie wir es verschwinden lassen können. Es ist eigentlich ganz einfach, dieses 🎜dom🎜-Element zu entfernen der richtige Zeitpunkt. Hier müssen wir es wissen Ein Punkt: Wir müssen searchBar
in den globalen Bereich der aktuellen Datei hochstufen. Wir können nicht einfach zu new
in open
gehen. SeachBar
erscheinen, die von unserem new
erzeugt wurde. Denken Sie darüber nach? Ich füge eine Variable hinzu, um zu bestimmen, ob isShowing angezeigt wird
. Wenn es angezeigt wird, rufe ich die Instanz auf, wenn der Benutzer erneut present
aufruft Ist es möglich, die Methode dismiss
zu verwenden, um es verschwinden zu lassen? new
in der Datei App.vue
, um dieses Suchfeld aufzurufen. Was aber, wenn wir hinzufügen, dass wir dieses Suchfeld jetzt in der Datei XXX.vue
aufrufen müssen? Muss ich es erneut einführen und dann erneut neu
? Nonono, ein großer Chef sagte, dass Programmierer sehr faul seien und keinen solchen repetitiven Code auf niedriger Ebene schreiben könnten. So erreichen Sie es🎜Öffnen Sie die zuvor vorbereitete useSearch.ts-Datei, konvertieren Sie die zuvor global generierte SearchBar-Instanz in App.vue
und erstellen Sie daraus eine globale App.vue
的全局生成的这个 SearchBar 实例转换思路,使它在全局的一个 ts 文件内生成一个,然后把这个实例自身的一些方法封装成函数,暴露给外部。那么我就可以在全局任意一个地方去调用这个实例身上的这两个方法。
让我们在 App.vue
去试一下。
这是我们之前的 App.vue
文件的调用方法。我们改造一下它。我们再次测试一下功能有没有什么问题
如此一来就方便很多了,我们可以在任意位置去调用这个“唯一的搜索框”
再此之前,我们需要理解一个概念,注意我们的 main.ts
文件,我们是把谁挂在了全局的那一个 id='app'
的真实 dom 下的?
没错,就是前面我们提到的 App.vue 组件。
那么假如我在这个 App.vue
组件挂载的时候,给全局 window 对象身上添加一个键盘事件,是不是就可以了呢?怎么添加呢?其实非常非常简单,要用到见组合按键,我们就需要使用到 “keydown”,具体为什么不是 “keypress” ,读者可以自行查阅这两者的区别,不属于本文的主要探讨内容。
这时候,我们先来按一下 command
看看打印的内容是什么。这里重点的内容是该键盘事件身上的metaKey
属性。在这里我们还可以推算出按下 “ctrl” 的事件为
keydown 事件支持多个按键同时按下。当我们同时按下 “command” 和 “K” 键,会发生什么呢?但是我们发现好像并没有 K:true
这个属性呀,那我们怎么去判断呢?别着急接着往下看。
我们可以看到键盘事件 event 身上有个 key 属性,它的值恰好是字符串类型的 “k”,
这里我直接公布写法,js 允许我们这样判断是否同时按下两个按键。
我们测试一下,我们去吧 App.vue 文件内的这两个按钮给去掉然后再打印一下我们按下 command
和 k
ts-Datei. Generieren Sie eine und kapseln Sie sie dann einige der Methoden dieser Instanz selbst in Funktionen umwandeln und sie nach außen zugänglich machen. Dann kann ich diese beiden Methoden für diese Instanz überall auf der Welt aufrufen.
App.vue
. App.vue
-Datei. Lass es uns transformieren. Lassen Sie uns die Funktion noch einmal testen Gibt es ein Problem? br/>Das ist viel praktischer. Wir können dieses „nur Suchfeld“ an jedem Ort aufrufen.
main.ts
-Datei achten, wer wir in der globalen id='app'
hängen, ist wirklich dom?
Nr Falsch, es ist die
App.vue
-Komponente ein Tastaturereignis zum globalen 🎜window🎜-Objekt hinzufüge, ist das dann in Ordnung? Wie füge ich es hinzu? Tatsächlich ist es sehr, sehr einfach, die Tastenkombination „keydown“ zu verwenden. Insbesondere können die Leser den Unterschied zwischen den beiden selbst überprüfen nicht der Hauptdiskussionsinhalt dieses Artikels. 🎜🎜🎜🎜this Klicken wir zunächst auf Befehl
, um zu sehen, was gedruckt wird. Der Fokus liegt hier auf dem Attribut metaKey
für das Tastaturereignis. Hier können wir es noch wird abgeleitet, dass das Ereignis des Drückens von 🎜"Strg"🎜 🎜🎜🎜🎜🎜keydown🎜-Ereignis unterstützt das gleichzeitige Drücken mehrerer Tasten. Was passiert, wenn wir gleichzeitig die Tasten „Befehl“ und „K“ drücken? Aber wir haben es gefunden Scheint nicht zu sein. Es gibt kein K:true
-Attribut. Wie beurteilen wir es also? Machen Sie sich keine Sorgen und schauen Sie weiter nach unten. 🎜🎜🎜🎜Wir können sehen, dass das Tastaturereignis 🎜event🎜 ein Attribut 🎜key🎜 hat und sein Wert zufällig vom Zeichenfolgentyp 🎜"k"🎜 ist, 🎜command
und k
drücken. 🎜Testen Sie es: 🎜🎜🎜🎜🎜 7. Fügen Sie die angezeigte Animation hinzu 🎜🎜🎜🎜Wie wir oben sehen können, scheint das plötzliche Erscheinen etwas abrupt zu erfolgen. Ich hoffe, dass dieses Suchfeld beim Erscheinen einen leichten Schwenkeffekt haben kann (ähnlich wie unten). Wie kann ich das tun? ?🎜🎜Hier stelle ich eine einfachere Idee vor. Wir haben eine Css-Animation im Stil der App.vue
-Datei voreingestellt ein guter Name. Es heißt"searchInput"App.vue
文件的 style 内预设一个 Css 动画,并起好名字。叫做 "searchInput"
然后回到我们 searBar.vue
的组件去,给我们这个组件最外层的起一个好听的名字,我这里就叫做 searchBarWrapper
。
然后回到我们的 SearchBar.ts
文件内,也就是放我们 SeachBarCreator 构造函数的那个文件内。(tips:不是 useSearch.ts 哦)
我这里解释一下思路,在调用 render 函数后,这个组件其实已经渲染成为一个真实的 dom 元素,只不过我们还没给它指定渲染的位置。既然是真实的 dom ,那么我们就可以通过 document.getElementById这个方法(querySelector同理,一个意思)
拿到这个SearchBar.vue组件
,接下来我只需要在调用 document.body.insertBefore
方法前,给它添加上刚刚我们在 App.vue
里预设好的类名,searchInput
,就完美达成我们想要的效果了。
注意:style ,这个点仅仅是类名选择器,不要忘记了基础知识。
测试一下效果:
在弹出框的 input 框实现自动聚焦相比于之前讲的就非常简单了,我在这里一笔带过了。只需要在 nextTick 中调用 input 本身的 focus 方法即可。
之所以不喜欢使用真代码去写文章而大量使用截图的原因是:我自己在搜索到自己想要的文章后,也会喜欢直接看有没有最后的成品代码,然后直接复制就拿过去用了,而往往忽略了自己动手去实现一遍才是真正理解了的过程。
所以我写代码的时候,尽量不写特别复杂的逻辑,而写一些很简单的几行代码去实现某一个功能。是因为我希望你们真正带入自己的思考,和一步步体会这个实现过程,从而举一反三。
如果你认真看了该文章,你也许会明白现在很多组件库的底层实现原理其实就是这样的,比如全局弹出的dialog ,modal 框等等。我们要去理解组件库组件实现的思路,而不是一味的复制粘贴。
这个搜索框有很多可以更加优化的地方,你们可以带入自己的思考去想一想。比如
1.如何保存搜索历史?
2.如何实现实时的给出搜索联想
与君共勉才是我的初衷...
这里贴出核心代码 SearchBar.ts
SearchBar.ts
, der Datei, in der sich unser SeachBarCreator-Konstruktor befindet. (Tipps: Es ist nicht useSearch.ts)
Lassen Sie mich die Idee hier erklären. Nach dem Aufruf der render-Funktion wurde diese Komponente tatsächlich in ein echtes dom-Element gerendert, aber wir haben noch nicht die Renderposition dafür angegeben . Da es sich um einen echten Dom handelt, können wir diese SearchBar.vue-Komponente
über die Methode document.getElementById (dasselbe wie querySelector, dieselbe Bedeutung) code>, dann muss ich nur den Klassennamen hinzufügen, den wir gerade in <code>App.vue
voreingestellt haben, bevor ich die Methode document.body.insertBefore
aufrufe wird perfekt den gewünschten Effekt erzielen. 🎜🎜🎜🎜Achtung :Stil, dieser Punkt ist nur ein Klassennamenselektor, vergessen Sie nicht die Grundlagen. 🎜🎜🎜🎜Test Hier ist der Effekt: 🎜 🎜SearchBar.ts
wird hier veröffentlicht. Ich hoffe, dass die Leser ihn nur als Referenz verwenden können und ihn nicht direkt kopieren und einfügen müssen. 🎜import { h, render } from "vue" import SearchBar from "./SearchBar.vue" class SearchBarCreator { container: HTMLElement appElement: HTMLElement | null showing: boolean _dismiss: () => void constructor() { this.container = document.createElement("div") this.showing = false this.appElement = document.body.querySelector("#app") this.present.bind(this) this.dismiss.bind(this) this._dismiss = this.dismiss.bind(this) } present() { if (this.showing) { this.dismiss() } else { const SearchBar = h(h(SearchBar)) render(SearchBar, this.container) const searchBarWrapperDOM = this.container.querySelector("#searchBarWrapper") searchBarWrapperDOM?.classList.add("animate-searchInputAnimation") document.body.insertBefore(this.container, document.body.firstChild) this.showing = true this.appElement?.addEventListener("click", this._dismiss) } } dismiss() { if (this.showing && this.container) { render(null, this.container) document.body.removeChild(this.container) this.showing = false this.appElement?.removeEventListener("click", this._dismiss) } else { console.log("不需要关闭") } } }
Das obige ist der detaillierte Inhalt vonDetaillierte grafische Erläuterung der Schritte zur Implementierung des globalen Suchfelds in Vue3 (mit Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!