首頁 >web前端 >Vue.js >圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

藏色散人
藏色散人轉載
2023-01-13 16:22:213265瀏覽
##@charset "UTF-8";@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}.markdown-body{word-break:斷字;行高:1.75;字體粗細:400;字體大小:15px;溢出-x:隱藏;顏色:#36ace1;背景圖像:線性漸變(90deg,rgba(217,234,251,.25) 3%,透明0),線性漸變(1turn,rgba(217,234,251,.25) 3%,透明0);背景大小:20px 20px;背景位置:50%}.markdown-body h1,.markdown-正文h2,.markdown-body h3,. markdown-body h4,.markdown-body h5,.markdown-body h6{顏色:#36ace1}.markdown-body h1:之前,.markdown-body h2:之前,.markdown -body h3:之前,.markdown-body h4:之前,.markdown-body h5:之前,.markdown-body h6:之前{內容:"";顯示:塊;位置:絕對;左:0;頂部:0 ;底部:0;邊距:自動;背景影像:url(資料:影像/ png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd UAAAF8UlEQVRIS71Wa2wUVRT 7r0zu9t2t/RBaSioPCpYbIUfaEIQUogOxJIUSGwxEv影響MGBVqhpUCfW3Zn5z7MuQOE0hYxMdxJdmd25s53vnO 851leMCLPWA8/CFA2TsvL8n7q NTFNLG 4VqInHOeJLDQMzdz/3r4DGGDb9lxu aPCE7U610DDJDADoo Ahv6c8hbDDwRiQlgYGDOcaWyEcjg8On j71IpJndjGt9XO jM7 pkywNvbazIfercieSdoJ4bE5sWjyZqMpDdeaQNXMNC34ME3LV8B56 1w3AOgkEXMpDdeaQNXMNC34ME3LV8B56 1w3AOgkEXMpDdeaQNXMNC34ME3LV8B56 1w3AOgk zQ1CGkBhwOCMFAB71U0qsYgRlwBtQ1tiEJAy44OBdQUmFK3aWS06NLT ukZAQoKCCjsfbDmk6p78RwX3ncWffmIj8U4kh6GpEwh 9r78RwX3ncWffmIj8U4kh6GpEwh 9rCy23LDU4998U4kh6GpEwh 9r/Er/A433F4203FF42000300000230002029 WM2TI8f jEyCmvjfn1FssuojHx6tDkyZOaCzr8TNpaSzDAk8amlRIrEylcSGsYrcGistiYWhgDDIM2BiGH3ywFkGAC1U9n38bpVqWGdk6r4HMWrZaG1CkGAC1U9n38bpVqWGdk6 vK8sVHe8JsU0U6uO5hlexo8PI7vNDQomwoBRAwpSmtgJAAztS3QLsOsmBQlBtFJMQhlbbPUBBUR7o2hqHVddLbRsfCPQJ u3TPw8uGl1yyyaUR7o2hqHVddLbRsfCPQJ u3TPw8uGl1yyyiAlpakAmMakm/MakpMM5545FpF5pM5FpF5pF5pF5pF5pF5pF5pF5p5pM5p,ApF 4UYSsnet3UMM5HPT5LGbrDGYQroClyT2Jwnyj9aN949e8mDCwuRFoqKxRHUJ21BSDRELuQYGhvbMVV32Dp2RuxcfHSRBfAYTsbU9nJdFj5EiLkglHKRC1CDVDDDDDDDDDDDDD姆5 itpxh64ZtsT6b5ie6pPRkfF90TllxOzEwmipMKRRgHODGgCuJkqIcvDdC2BZ5Y tlHHMzkAKghbAxcQqQDiKrFBxhqg5MHtivS1tQAQ s6AxcQqQDiKrFBxhqg5MHtivS1tQAQ s6Ql5156L1L1tFFL Kl9IKjAsbJaWfzo1USDsM6zceDJfeVGgnhhN2N7YOyo5kJz1pa2AbgfrO1gRwXW6vSRQNtddR EhvKGmseskgTtY2Q7kucYWWgToPHzyUyXry0iXhvKGmseskgTtY2Q7kucYWWmToPHzyUyXry0iX pKxyh/N0/vTToubtH1G3RmLjhM8ubKXfWB2mRa9ySOaWS2ut8lTZ0cI6I52Ngv7zAbW9mQVm1cpytu441P38XextlQu e46nyh bjLkMQVm1cpytu441P38XextlQu e46nyh bjLkMZRU0MCBTCJMwWpWMFBTA4T445BLkLkMZRUPTC /vPynBk9MqRIiOWs8a2WJTm9a cgh6SamIMz9W1WjYHHMtv0wSmZdWB9gdsya/rcYVg7JoffCdqlD6ceTpiY59tM0PhJp5WNvra BQkejoffCdqlD6ceTpiY59tM0PhJp5WNvra BQkejCMCdqlD6ceTpiY59tM0PhJp5WNvra BQkejCMCdqlD6ceTpiY59tM0PhJp5WNvra BQkejCM N0fBsu21fTvL6PXnhxXlnLIqqhYYBian4lQ2Lk9ogiALsimiLC1QYfhlV1Hnxh7JfcMqxrpd7U2GFa5t9nOd7Kr kg4uWvnCproxrpd7U2GFa5t9nOd7Kr kg4uWvnCproproJeXlq 3Ox / 3Q7LRbsqH rKRJ NBA / WW7II1s9vvVBuNr7KNF1WUM1bSt5f1Vq01jUVkKfnx8uoti3Or5rbd9782M61azJz/ rFywYU /OyKqK1p5G2MS1Z18tGFDwTkvIxcK9RwaMP3a9/tbc62lPj/Nw5B9ey9Ehy/MY4oEqelgNleuyCgdXJlmc3fO5Ll56r5fOmqelgNleuyCgdXJlmc3fO5Ll50 .markdown-正文h1{位置:相對;字體大小:30px;填充:12px 38px;邊距:30px 0}. markdown -body h1:之前{寬度:30px;高度:30px;背景大小:30px 30px}.markdown-body h2{位置:相對;字體大小:24px;填充:12px 36px;邊距:28px 0}.markdown-正文h2:之前{寬度:28px;高度:28px;背景大小:28px 28px}.markdown-body h3{位置:相對;字體大小:18px;填充:4px 32px;邊距:26px 0}.markdown-body h3 :之前{寬度:24px;高度:24px;背景大小:24px 24px}.markdown-body h4{位置:相對;填充:4px 28px;字體大小:16px;邊距:22px 0}.markdown-body h4 :之前{寬度:20px;高度:20px;背景大小:20px 20px}.markdown-body h5{位置:相對;填充:4px 26px;字體大小:15px;邊距:20px 0}.markdown-body h5:之前{寬度:18px;高度:18px;背景大小:18px 18px}.markdown-body h6{位置:相對;填充:4px 22px;字體大小:14px;邊距:16px 0}.markdown-body h6:之前{寬度:16px ;高度:16px;背景尺寸:16px 16px}.markdown-body p{line-height:繼承;margin-top:22px;margin-bottom:22px}.markdown-body img{最大寬度: 100%}.markdown- body hr{位置:相對;寬度:98%;高度:1px;邊框:無;上邊距:32px;下邊距:32px;背景影像:線性漸變(90deg,#36ace1 ,#dff0fe,#36ace1);溢位:可見}.markdown-body hr:after{content:"";position:absolute;margin:auto;left:0;right:0;bottom:0;top:0;display:inline-block;width:50px;height:24px ;背景:#fff;背景影像:url(資料:影像/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAEgElEQVRIS72Va0xbZRjH/z2FcimbchEQFDYRCIRWFVRIS72Va0xbZRjH/z2FcimbchEQFDYRCIRWFQQ2MaC4m 4nRbuwpsXDYWLLoRgeG4Chu9QHvMOQ0dpTAKH3y/tDnv8/5/z/Oc//scBv6nxdgoJ14gVYPEUITHdTdHY12gRIH0T0KljlqwthqUFp ft/i7wc98MtrUFxmbU6ByYgFwxjtFp5Q WpF1mCy9wajXoqqD4E91saOf603e 5B7t99xTkyZJEiKJAl2DE9Xio1HvrBS8IuhVwV9503575722DE9Xio1HvrBS8IuhVwV9503000522267p du7NmtnQfx5zWm8Q8Ui3gyGcddyU8rv/STRNQouDGP5/mhTubX4dpPv3DMzh1qS9LwuPWr i63WVyn5QYj /4d /i4bqmbpoQ auvBlQYghX6PE4wTSOzV5EUYlb5Q4MDqLk9/3cMRF27spDSNQamUnWZ4ebNB OKNCyYVeFCZ5wZ5tiePN/UiP2YoQL0cUX i 0sxr0 XBZgbJUP6OiLnaM4ivZCBrzOWBZEIY9rY5E8pl2nM0KMzzLq5aPiXmRzgbQm2VyR8KGGK/ICAFB6IusbvsDwhRf n/jtSHc/nsG1K/ICAFB6IusbvsDwhRf n/jtSHc/nsG1BRK1B1BF1BF1BFBFF5>FFF線線 TK1BK1b7454>BJ35 月7oW 4KFJ/SV4/IScrc55kQj07WNuOn94Lpw8kCm/Qv3W5HLjbWxsyfuNUO1TzWjAJBloKt2FBS Jz6ShiA12NupBdLWugQcmn28lPMCC338575767567 月OPQ9 UCNpib6T1tkg RZ9KKJcNn8sJc1vac8o16jklLWLuOiDqwvHUIKPw7vtTON iCDKkl/Cx9FeSYET5um1mHt6jN0Dz9ftwYjORudNjTTdaBmi7kxPJndaBmidvJMJSYJFGJFGJTTdaBmidvMJMJSSJFin​​DPTSJSinSTSJSinSSSSSSSSSSDDDDD為了宗教面臨SDDDDGDDGDDDD 大多數S 大多數QDS?S%DSDDDDGDQDSD明明明S明 N今天命令二二二二二二二二二二二海二基二海基索萬EP1Hbh4yPj9LadSY6fu6gPsCX B3mq7NYLv2od8fj4aoViMNQGFijos/XVMTXGavgUisQIle71hwVx9KFEutLVjw8GORTuxoEbeJS7iPrmQyy/hwVx9KFEutLVjw8GORT? DA PC9xjLqo8foFkau2qaCeXSyvzXfA9SDrp1bxJ/ DU/jSJKXEWdBR2J/9U0UpwXTFZ/8S76h /71FvO4A8sTeuqQThDKalOiPLN3BbhiYlaNsm964elkCztrC4xMqeDqYIus2JdB3cbS5l4KCztrC4xMqe” Kx4pFSqXzxCn/X9Gr2NO zw cTiTbxmUyCq H3GlsWg2kRNhOnHmhlrFkIvHTZt1borWvMCmRnwH4usn58STiycAAAAAElFTkSuQmCC); -body程式碼{字體系列:Menlo、Monaco、Consolas、Courier New、等寬;斷字:break-word;邊框半徑:2px;overflow-x:auto;背景顏色:#282c34;顏色:#4ec9b0;填充: 。24em .46em;margin:0 4px}.markdown-body pre{overflow:auto;position:relative;line-height:1.75}.markdown-body pre>code{font-family:Menlo,Monaco,Consolas,Courier New ,等寬字體;字體大小:12px;邊框半徑:10px;填充:15px;邊距:0;斷字:正常;顯示:塊;溢出-x:自動;顏色:#4ec9b0;背景:#282c34}. markdown -body a{text-decoration:none;color:#409eff;border-bottom:1pxsolid #409eff}.markdown-body a:active,.markdown-body a:hover{color:#007bff;border-bottom:1px固體#007bff}.markdown-body表{顯示:內聯塊!重要;字體大小:12px;寬度:自動;最大寬度:100%;溢出:自動;邊框:1px固體#f6f6f6}.markdown-body thead{背景:#f6f6f6;顏色:#000;text-align:left}.markdown-body tr:nth-child(2n){背景顏色:#fcfcfc}.markdown-body td,.markdown-body th{填充:12px 7px;行高:24px}.markdown-body td{min-width:120px}.markdown-body blockquote{位置:相對;填充:8px 26px;背景顏色:rgba(54,172,225,.75);邊距:16px 0 ;左邊框:4px 實心#409eff;邊框半徑:5px}.markdown-body 區塊引用:之前{內容:「❝」;上:10px;左:8px;顏色:#409eff;字體大小:20px;line-height :1;font-weight:700;position:absolute;opacity:.7}.markdown-body blockquote:after{content:"❞";font-size:20px;position:absolute;right: 8px;bottom:0; color:#409eff;opacity:.7}.markdown-body blockquote>p{color:#fff}.markdown-body ol,.markdown-body ul{padding-left:28px}.markdown- body ol li,.markdown -body ul li{margin-bottom:0;list-style:inherit}.markdown-body ol li .task-list-item,.markdown-body ul li .task-list-item{列表-style:none}. markdown-body ol li .task-list-item ol,.markdown-body ol li .task-list-item ul,.markdown-body ul li .task-list-item ol,.markdown- body ul li .task- list-item ul{margin-top:0}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:3px }.markdown-body ol li{padding-left:6px}@media (max-width:720px){.markdown-body h1{font-size:24px}.markdown-body h2{font-size:20px}.markdown -body h3{字體大小:18px}}

這篇文章為大家帶來了關於Vue3的相關知識,其中主要介紹了Vue3是怎麼實現一個全局搜尋框,我會分享一下自己完整實現的思路,下面一起來看一下吧,希望對需要的朋友有幫助。

Vue3 如何實作一個全域搜尋框

前言:自從學習 vue 以來,就對 vue 官網全域的 command K 調出全域關鍵字搜尋這個功能心心念念。恰好最近專案也是需要實現一個全域搜尋的功能,也正好可以正大光明的帶薪學習這個功能的想法。網路上的教程水平參差不齊,而恰好之前的項目中我有做過一個類似於全局彈出麵包屑的功能,於是舉一反三寫出了一個我們項目需要的全局搜索框,特來分享一下自己的思路。

圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

注意:本文不會馬上教你如何寫程式碼,而是作為一個引路人,一步一步引導你去理解這個元件的設計思路。會以「假如我是個初學者,如果我在學習這個知識的時候,別人能這樣告訴我,那麼我也可以很快的去理解」 的角度去講解,授人以魚不如授人以漁。希望你在閱讀本文的時候可以拓展思路,舉一反三。

一. 文件準備

你需要先準備三個文件,來完成這個全域搜尋框

  • SearchBar.ts 檔案

  • SearchBar.vue 檔案

  • #useSearch.ts 檔案

圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

二. 搜尋框的樣式

樣式問題不是本文的重點,你可以花費五分鐘在SearchBar.vue 檔案內速寫一個非常簡易的正方形div 包裹著一個input 標籤即可快速進行下面的學習。

但是首先我們需要理清思路,這個元件是會出現在我們頁面的最頂端的,所以它元件內部需要用到絕對佈局。我們去SearchBar.vue 去設定一個樣式給最外層的div,這裡其它樣式的寫法使用的是Uno CSS,沒用過的小夥伴也不需要擔心,它只是單純的樣式,和本文中心內容不牽扯。 (CSS寫成計算屬性在這個場景也毫無特殊意義,只是單純設計時考慮多了)圖文詳解Vue3實作全域搜尋框步驟(附程式碼)圖文詳解Vue3實作全域搜尋框步驟(附程式碼)圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

#三.渲染函數hrender 函數(重點)

  • 打開之前準備的SearchBar.ts 文件,從vue 引入這兩個函數,並且把上一步寫好的簡陋版搜尋框(SearchBar.vue)引入這個檔案內。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

  • 看過我之前文章Vue3實作一個Toast 的讀者可能會比較熟悉一點點,但在那一篇文章內由於我也是初次接觸這兩個函數,所以當時總結的也不是特別精確,所以重新捋清思路,這裡再講解一下。

  • 首先我們從官網的介紹,先來看看這個函數的定義。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)
    可以看出,這個函數第一個參數是必填的,可以是一個stringComponent,這篇文章重點討論參數為 Component 的情況。重點是這個函數的回傳值,是一個VNode,這個你一定不陌生,Virtual Node ,看這篇文章的讀者可能對虛擬dom 的原理可能不是那麼清楚,但我相信你們一定知道它的基本機制。 Vue 其實是先渲染 虛擬 dom -->然後 轉換成真實 dom

  • 先別急著寫程式碼,我想你可能更清楚這樣的寫法,例如我們前面在 SearchBar.vue 檔案內寫的簡單的彈出框。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)整個元件的樣式都是在Vue 提供的 元件內寫的,但是你要知道,Vue 在底層還是透過呼叫h() 來完成虛擬dom 的建置。而 只是 Vue 為了讓你用熟悉的原生 html 開發而為你提供的語法糖?而已。 (嗯,你可以這樣理解)

  • 那麼我們可以根據上面h() 函數的介紹,它接收的第一個參數可以是Component ,那我們這個SearchBar.vue 不就是元件嗎?那如果我不想使用 去展示這個組件的話,我是否可以這樣寫呢? h(SearchBar.vue)。沒錯,是的,你就是可以這樣寫。別忘了 h 的回傳值就是我們想要拿到的 Vnode ,所以依照正確的寫法是這樣的。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

三. 寫SearchBarMaker 建構子和present 方法

  • ##讓我們回到

    SearchBar.ts 檔案。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

  • 首先思考,這個搜尋框一定有一個出現的函數,和一個消失的函數?,ok,起名字,一個

    present,一個dismiss
    圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

  • 接下來我需要建立一個

    VNode ,然後想辦法處理成真實 dom。經過上面的學習,第一步馬上就可以想到下面的寫法。
    圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

  • 下面這位比較是重量級,

    render() 函數。虛擬 dom 有了,真實dom 該如何拿到? Vue 為我們提供了這樣一個函數,這裡我們需要重點去看這個函數的型別是值,是一個 RootRenderFunction 類型的。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

  • 這裡我們轉換思路,我們看一下

    render 函數的第二個參數是一個container:HostElement ,然後讓我們打開我們main.ts 文件,我們跳進mount的定義部分,圖文詳解Vue3實作全域搜尋框步驟(附程式碼)發現神奇的地方了嗎,我們雖然不知道圖文詳解Vue3實作全域搜尋框步驟(附程式碼)HostElement 的型別是什麼,但你知道你mount 函數內填的參數是什麼了嗎? (忘掉的轉頭自覺複習官網哈。)沒錯,就是全局唯一的一個真實
    dom,一個樸實無華的id叫appdiv 元素。 由於篇幅限制,在這裡你可以先暫時簡單的理解,圖文詳解Vue3實作全域搜尋框步驟(附程式碼)render 函數會將你的虛擬dom 包裝成一個真實dom 元素,但是你需要給它一個真實的外殼dom 來告訴它將虛擬dom 渲染到哪個位置。

  • ok,拿到一個包裝好的虛擬 dom ,接下來就是告訴瀏覽器在哪裡渲染這個元素。這裡我們需要思考?,既然是全局都可以彈出的,並且需要在所有元件之上彈出。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)那麼最簡單的方法就是讓它出​​現在body的第一個元素,那麼它一定會和我們網頁所有的元件同級(tips:通常我們所有的頁面組成都會寫在body內 的一個div 內。什麼?你問我為什麼?請開啟你的index.html 看一下,你是否忘記了我們的App.vue 是掛在這個真實的,id為app 的元素內的)圖文詳解Vue3實作全域搜尋框步驟(附程式碼)那其實我們的操作的思路就是非常簡單的,當我按下全域搜尋按鈕,那麼你就在<div id="app"> 的元素之前插入我的元件即可。 <img src="https://img.php.cn/upload/article/000/000/020/659e9d144b30400682dc69d8bf2b853c-18.png" alt="圖文詳解Vue3實作全域搜尋框步驟(附程式碼)" loading="lazy"><li><p>ok,到這裡我們已經可以看到基本效果了,我們來測試一下。讓我們在 <code>App.vue 元件內隨便寫一個按鈕,然後呼叫 SearchBarCreator 實例身上的 present 方法。 (maker 感覺不是那麼合理,之後我們將SearchBarMaker 變更為SeachBarCreator 的叫法,僅僅是名字變了而已,邏輯什麼的根本沒變哦.?)圖文詳解Vue3實作全域搜尋框步驟(附程式碼)效果如下:
    圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

  • 到這裡searchBar 已經可以呈現在頁面上了,但是我們還不知道怎樣讓它消失,其實也非常簡單,我們只需要在適當的時機移除這個dom 元素。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)在這裡我們需要知道一點,我們需要將 searchBar 提升到目前檔案的全域,不能只在 open中去 new 了。
    圖文詳解Vue3實作全域搜尋框步驟(附程式碼)ok,我們測試一下
    圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

  • 四. 最佳化SearchBarCreator 建構子的程式碼邏輯

    #寫到這裡的時候,你可能發現了一個小問題,當我一直去按搜尋按鈕的時候,它會出現多個搜尋框,但是我們希望的是它在全域只能出現一個搜尋框。換個角度思考,也就是同一時間,這個被我們 new 出來的 SeachBar 實例只能出現一個。思考一下?,我加一個變量,isShowing 是否正在被展示 ,如果正在被展示的話,那麼用戶再次調用present 的時候,我就去調用實例自身的dismiss 方法讓它消失,是否可行呢?
    圖文詳解Vue3實作全域搜尋框步驟(附程式碼)測試一下:
    圖文詳解Vue3實作全域搜尋框步驟(附程式碼)
    OK,看來完美解決目前的問題了。

    五. 寫全域唯一的呼叫實例

    • 在上面的這種情況下,我們已經可以在App.vue 檔案內去new 一個實例來呼叫這個搜尋框了。但是我們加入現在需要在 XXX.vue 檔案內呼叫這個搜尋框呢?我還需要重新去引入,然後重新 new 嗎? nonono,某位大佬說過,程式設計師都是很懶的,不可能寫這種低階的重複程式碼的。那麼該如何實現呢

    • 打開我們之前準備的useSearch.ts 文件,我們把之前在App.vue 的全局生成的這個SearchBar 實例轉換思路,使它在全域的一個ts 檔案內產生一個,然後把這個實例本身的一些方法封裝成函數,並暴露給外部。那我就可以在全域任意一個地方去呼叫這個實例身上的這兩個方法。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    • 讓我們在 App.vue 去試試看。
      這是我們之前的 App.vue 檔案的呼叫方法。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)我們改造一下它。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)我們再次測試一下功能有沒有什麼問題圖文詳解Vue3實作全域搜尋框步驟(附程式碼)
      如此一來就方便很多了,我們可以在任意位置去調用這個「唯一的搜尋框」

    #六. 在新增全域的快捷鍵Command K

    • 再此之前,我們需要先理解一個概念,注意我們的main.ts 文件,我們是把誰掛在了全局的那一個id='app' 的真實dom 下的? 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)
      沒錯,就是前面我們提到的 App.vue 元件。

    • 那麼假如我在這個App.vue 元件掛載的時候,給全域window 物件身上加上一個鍵盤事件,是不是就可以了呢?怎麼添加呢?其實非常非常簡單,要用到見組合按鍵,我們就需要使用到“keydown”,具體為什麼不是“keypress” ,讀者可以自行查閱這兩者的區別,不屬於本文的主要探討內容。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    • 這時候,我們先來按一下 command 看看列印的內容是什麼。這裡重點的內容是該鍵盤事件身上的metaKey 屬性。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)在這裡我們也可以推導出按下「ctrl」 的事件為圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    • keydown# 事件支援多個按鍵同時按下。當我們同時按下 “command” 和 “K” 鍵,會發生什麼事? 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)但我們發現好像並沒有 K:true 這個屬性呀,那我們怎麼去判斷呢?別急接著往下看。

    • 我們可以看到鍵盤事件event 身上有個key 屬性,它的值恰好是字串類型的“ k”圖文詳解Vue3實作全域搜尋框步驟(附程式碼)


    這裡我直接公佈寫法,js 允許我們這樣判斷是否同時按下兩個按鍵。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    • 我們測試一下,我們去吧App.vue 檔案內的這兩個按鈕給去掉圖文詳解Vue3實作全域搜尋框步驟(附程式碼)然後再列印我們按下commandk 的時候。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)測試一下:圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    七. 新增出現的動畫

    • 在上面我們可以看到,這樣突然的出現好像有一絲絲的突兀。我希望這個搜尋框在出現的時候,可以有那麼一絲絲的平移效果,(類似下面的效果)該如何做呢? ?圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    • 我在這裡介紹一個較為簡單的思路,我們在App.vue 檔案的style 內預設一個Css動畫,並起好名字。叫做"searchInput"圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    • 然後回到我們searBar.vue 的元件去,給我們這個元件最外層的取一個好聽的名字,我這裡就叫做searchBarWrapper圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    • 然後回到我們的 SearchBar.ts 檔案內,也就是放我們 SeachBarCreator 建構子的那個檔案內。 (tips:不是 useSearch.ts 哦) 我在這裡解釋一下思路,在呼叫 render 函數後,這個元件其實已經渲染成一個真實的 dom 元素,只不過我們還沒給它指定渲染的位置。既然是真實的dom ,那麼我們就可以透過document.getElementById這個方法(querySelector同理,一個意思)拿到這個SearchBar.vue元件,接下來我只需要在呼叫document.body.insertBefore 方法前,給它加上上剛剛我們在App.vue 裡預設好的類別名,searchInput ,就完美達成我們想要的效果了。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    • 注意:style ,這個點只是類別名稱選擇器,不要忘記了基礎知識。 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    • 測試效果:圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    #八.自動對焦

    在彈出框的input 框實現自動聚焦比起之前講的就非常簡單了,我在這裡一筆帶過了。只需要在 nextTick 中呼叫 input 本身的 focus 方法即可。
    圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

    總結:

    之所以不喜歡用真程式碼去寫文章而大量使用截圖的原因是:我自己在搜尋到自己想要的文章後,也會喜歡直接看有沒有最後的成品程式碼,然後直接複製就拿過去用了,而往往忽略了自己動手去實現一遍才是真正理解了的過程。

    所以我寫程式碼的時候,盡量不寫特別複雜的邏輯,而寫一些很簡單的幾行程式碼去實現某一個功能。是因為我希望你們真正帶入自己的思考,和一步步體會這個實現過程,從而舉一反三。

    如果你認真看了該文章,你也許會明白現在很多元件庫的底層實作原理其實就是這樣的,例如全域彈出的dialogmodal框等等。我們要去理解元件庫元件實現的思路,而不是一味的複製貼上。

    這個搜尋框有很多可以更優化的地方,你們可以帶入自己的思考去想一想。例如

    1.如何保存搜尋歷史記錄?
    2.如何實現即時的給予搜尋聯想

    與君共勉才是我的初衷...

    原始碼

    #這裡貼出核心程式碼SearchBar.ts 檔案的源碼,希望讀者可以只作為參考使用,希望不要直接複製貼上。

    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("不需要关闭")
        }
      }
    }

    推薦學習:《vue.js影片教學

#

以上是圖文詳解Vue3實作全域搜尋框步驟(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.im。如有侵權,請聯絡admin@php.cn刪除
上一篇:解析Vue2實作composition API的原理下一篇:解析Vue2實作composition API的原理

相關文章

看更多