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

##@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="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/020/659e9d144b30400682dc69d8bf2b853c-18.png?x-oss-process=image/resize,p_40" class="lazy" 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。如有侵權,請聯絡admin@php.cn刪除
當vue.js虛擬DOM檢測變化時會發生什麼?當vue.js虛擬DOM檢測變化時會發生什麼?May 14, 2025 am 12:12 AM

whenthevue.jsvirtualdomdetectschange,itupdatesthevirlualdom,diffsit和appliesminimalchangeStothereAldom.thisprocessensuresrocessensureshighhighpperformance byformance byavoidingunnnnnnnnnnneclastory dommaniplastions。

將Vue.js的虛擬DOM視為真實DOM的鏡像是多麼準確?將Vue.js的虛擬DOM視為真實DOM的鏡像是多麼準確?May 13, 2025 pm 04:05 PM

Vue.js的VirtualDOM既是真實DOM的鏡像,又不完全是。 1.創建和更新:Vue.js基於組件定義創建VirtualDOM樹,狀態變化時先更新VirtualDOM。 2.差異和修補:通過diff操作比較新舊VirtualDOM,僅將最小變化應用到真實DOM。 3.效率:VirtualDOM允許批量更新,減少直接DOM操作,優化渲染過程。 VirtualDOM是Vue.js優化UI更新的戰略工具。

vue.js vs.反應:可伸縮性和可維護性vue.js vs.反應:可伸縮性和可維護性May 10, 2025 am 12:24 AM

Vue.js和React在可擴展性和可維護性上的表現各有優勢。 1)Vue.js易於上手,適合小型項目,CompositionAPI提升了大型項目可維護性。 2)React適用於大型複雜項目,Hooks和虛擬DOM提高了性能和可維護性,但學習曲線較陡峭。

vue.js和React的未來:趨勢和預測vue.js和React的未來:趨勢和預測May 09, 2025 am 12:12 AM

Vue.js和React的未來趨勢和預測分別是:1)Vue.js將在企業級應用中廣泛應用,並在服務端渲染和靜態站點生成方面有突破;2)React將在服務器組件和數據獲取方面創新,並進一步優化並發模式。

Netflix的前端:深入研究其技術堆棧Netflix的前端:深入研究其技術堆棧May 08, 2025 am 12:11 AM

Netflix的前端技術棧主要基於React和Redux。 1.React用於構建高性能的單頁面應用,通過組件化開發提升代碼重用性和維護性。 2.Redux用於狀態管理,確保狀態變化可預測和可追踪。 3.工具鏈包括Webpack、Babel、Jest和Enzyme,確保代碼質量和性能。 4.性能優化通過代碼分割、懶加載和服務端渲染實現,提升用戶體驗。

vue.js和前端:構建交互式用戶界面vue.js和前端:構建交互式用戶界面May 06, 2025 am 12:02 AM

Vue.js是一種漸進式框架,適用於構建交互性強的用戶界面。其核心功能包括響應式系統、組件化開發和路由管理。 1)響應式系統通過Object.defineProperty或Proxy實現數據監聽,自動更新界面。 2)組件化開發允許將界面拆分為可複用的模塊。 3)VueRouter支持單頁面應用,提升用戶體驗。

Vuejs的缺點是什麼?Vuejs的缺點是什麼?May 05, 2025 am 12:06 AM

Vue.js的主要缺點包括:1.生態系統相對較新,第三方庫和工具不如其他框架豐富;2.學習曲線在復雜功能上變得陡峭;3.社區支持與資源不如React和Angular廣泛;4.大型應用中可能遇到性能問題;5.版本升級與兼容性挑戰較大。

Netflix:揭開其前端框架Netflix:揭開其前端框架May 04, 2025 am 12:16 AM

Netflix使用React作為其前端框架。 1.React的組件化開發和虛擬DOM機制提高了性能和開發效率。 2.使用Webpack和Babel優化代碼構建和部署。 3.採用代碼分割、服務端渲染和緩存策略進行性能優化。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境