Vue3 怎样完结一个大局搜索框
敞开成长之旅!这是我参加「日新方案 12 月更文挑战」的第1天,点击检查活动详情
前语:自从学习 vue 以来,就对 vue 官网大局的 command + K 调出大局关键词搜索这个功用心心念念。刚好最近项目也是需求完结一个大局搜索的功用,也正好能够光明磊落的带薪学习这个功用的思路。网上的教程水平良莠不齐,而刚好之前的项目中我有做过一个类似于大局弹出面包屑的功用,所以触类旁通写出了一个咱们项目需求的大局搜索框,特来分享一下自己的思路。
留意:本文不会立刻教你怎样编写代码,而是作为一个引路人,一步一步引导你全了解思路。会以 “假如我是一个初学者,假如我在学习这个常识的时分,别人能这样告诉我,那么我也能够很快的去了解” 的视点去解说 ,授人以鱼不如授人以渔。期望你在阅览本文的时分能够拓展思路,触类旁通。
一. 文件预备
前期你需求预备三个文件,来完结这个大局搜索框
- SearchBar.ts 文件
- SearchBar.vue 文件
- useSearch.ts 文件
二. 搜索框的款式
款式问题不是本文的要点,你能够花费五分钟在 SearchBar.vue 文件内速写一个十分简易的正方形 div 包裹着一个 input 标签即可快速进行下面的学习。
可是首要咱们需求理清思路,这个组件是会呈现在咱们页面的最顶部的,所以它组件内部需求用到肯定布局。咱们去 SearchBar.vue
去设置一个款式给最外层的 div
,这儿其它款式的写法运用的是 Uno CSS
,没用过的小伙伴也不需求忧虑,它仅仅单纯的款式,和本文中心内容不牵扯。(CSS写成核算特点在这个场景也毫无特殊含义,仅仅单纯设计时考虑多了)
三. 烘托函数 h 和 render 函数(要点)
-
翻开之前预备的 SearchBar.ts 文件,从 vue 里引进这两个函数,而且把在上一步写好的粗陋版搜索框(SearchBar.vue)引进到这个文件内。
-
看过我之前文章 Vue3完结一个 Toast 的读者或许会比较了解一点点,可是在那一篇文章内由于我也是初度接触这两个函数,所以其时总结的也不是特别精确,所以从头捋清思路,这儿再解说一下。
-
首要咱们从官网的介绍,先看一下这个函数的界说。
能够看出,这个函数榜首个参数是必填的,能够是一个string
和Component
,这篇文章要点评论参数为Component
的状况。要点是这个函数的返回值,是一个VNode
,这个你一定不生疏,Virtual Node ,看本篇文章的读者或许对虚拟 dom 的原理或许不是那么清楚,可是我相信你们一定知道它的根本机制。Vue 其实是先烘托 虚拟 dom –>然后 转化成实在 dom。 -
先别急着写代码,我想你或许更清楚这样的写法,比方咱们前面在 SearchBar.vue 文件内写的简略的弹出框。 整个组件的款式都是在 Vue 供给的 <template> 组件内写的,可是你要知道,Vue 在底层仍是通过调用 h() 来完结虚拟 dom 的构建。而 <template> 仅仅仅仅 Vue 为了让你用了解的原生 html 开发而为你供给的语法糖罢了。(嗯,你能够这样了解)
-
那么咱们能够依据上面 h() 函数的介绍,它接纳的榜首参数能够是
Component
,那咱们这个SearchBar.vue
不便是组件吗?那假如我不想运用 <template> 去展示这个组件的话,我是否能够这样写呢?h(SearchBar.vue)
。没错,是的,你便是能够这样写。别忘了h
的返回值便是咱们想拿到的 Vnode ,所以按照正确的写法是这样的。
三. 编写 SearchBarMaker 结构函数和 present 办法
-
让咱们回到
SearchBar.ts
文件。 -
首要考虑,这个搜索框一定有一个呈现的函数,和一个消失的函数,ok,起名字,一个 present,一个 dismiss 。
-
接下来我需求创建出一个 VNode ,然后想办法处理成实在 dom。经过上面的学习,榜首步立刻就能够想到下面的写法。
-
下面这位更是重量级,
render()
函数。虚拟 dom 有了,实在dom 该怎样拿到呢? Vue 为咱们供给了这样一个函数,这儿咱们需求要点去看这个函数的类型是值,是一个RootRenderFuncion
类型的。 -
这儿咱们改变一下思路,咱们看一下 render 函数的第二个参数是 一个 container:HostElement ,然后让咱们翻开咱们 main.ts 文件,咱们跳进
mount
的界说部分, 发现神奇的地方了吗,咱们尽管不知道 HostElement 的类型是什么,可是你知道你mount
函数内填的参数是什么了吗?(遗忘的回头自觉复习官网哈。)
没错,便是大局仅有的一个实在 dom,一个朴实无华的id叫app
的 div 元素。 由于篇幅限制,在这儿你能够先暂时简略的了解,render 函数会将你的虚拟 dom 包装成一个实在 dom 元素,可是你需求给它一个实在的 外壳dom 来告诉它将虚拟 dom 烘托到哪个方位。 -
ok,拿到一个包装后的虚拟 dom ,接下来便是告诉浏览器在哪里烘托这个元素。这儿咱们需求考虑,既然是大局都能够弹出的,而且需求在一切组件之上弹出。 那么最简略的办法便是让它呈现在 body的榜首个元素,那么它一定会和咱们网页一切的组件同级别(tips:通常咱们一切的页面构成都会写在 body内 的一个 div 内。什么?你问我为什么?请翻开你的 index.html 看一下,你是否忘记了咱们的 App.vue 是挂在这个实在的,id为 app 的元素内的) 那其实咱们的操作的思路便是十分简略的,当我按下大局搜索按钮,那么你就在
<div id="app">
的元素之前刺进我的组件即可。 -
ok,到这儿咱们现已能够看到根本作用了,咱们来测验一下。让咱们在
App.vue
组件内随便写一个按钮,然后调用SearchBarCreator
实例身上的present
办法。(maker 感觉不是那么合理,之后咱们将SearchBarMaker
变更为SeachBarCreator
的叫法,仅仅是名字变了罢了,逻辑什么的根本没变哦。) 作用如下:
-
到这儿 searchBar 现已能够呈现在页面上了,可是咱们还不知道怎样让它消失,其实也十分简略,咱们只需求在适宜的时机移除这个 dom 元素即可。 在这儿咱们需求知道一点,咱们需求将
searchBar
提升到当时文件的大局,不能仅只在open
中去new
了。
ok,咱们测验一下
四. 优化 SearchBarCreator 结构函数的代码逻辑
写到这儿的时分,你或许发现了一个小问题,当我一直去按搜索按钮的时分,它会呈现多个搜索框,可是咱们期望的是它在大局只能呈现一个搜索框。换个视点考虑,也便是同一时间,这个被咱们 new
出来的 SeachBar
实例只能呈现一个。考虑一下,我加一个变量,isShowing 是否正在被展示
,假如正在被展示的话,那么用户再次调用 present
的时分,我就去调用实例自身的 dismiss
办法让它消失,是否可行呢?
测验一下:
OK,看来完美解决当时的问题了。
五. 编写大局仅有的调用实例
-
在上面的这种状况下,咱们现已能够在
App.vue
文件内去new
一个实例来调用这个搜索框了。可是咱们加入现在需求在XXX.vue
文件内调用这个搜索框呢?我难道还需求从头去引进,然后从头new
吗?nonono,某位大佬说过,程序员都是很懒的,不或许写这种初级的重复代码的。那么该怎样完结呢 -
翻开咱们之前预备的 useSearch.ts 文件,咱们把之前在
App.vue
的大局生成的这个 SearchBar 实例转化思路,使它在大局的一个 ts 文件内生成一个,然后把这个实例自身的一些办法封装成函数,暴露给外部。那么我就能够在大局恣意一个地方去调用这个实例身上的这两个办法。 -
让咱们在
App.vue
去试一下。
这是咱们之前的App.vue
文件的调用办法。 咱们改造一下它。 咱们再次测验一下功用有没有什么问题
如此一来就便利许多了,咱们能够在恣意方位去调用这个“仅有的搜索框”
六. 增加大局的快捷键 Command + K
-
再此之前,咱们需求了解一个概念,留意咱们的
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
的时分。 测验一下:
七. 增加呈现的动画
-
在上面咱们能够看到,这样忽然的呈现如同有一丝丝的突兀。我期望这个搜索框在呈现的时分,能够有那么一丝丝的平移作用,(类似于下面的作用)该怎样做呢?
-
我这儿介绍一种较为简略的思路,咱们在
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.怎样完结实时的给出搜索联想
与君共勉才是我的初衷…