目錄
Vue3 如何實作一個全域搜尋框
一. 文件準備
二. 搜尋框的樣式
#三.渲染函數hrender 函數(重點)
三. 寫SearchBarMaker 建構子和present 方法
四. 最佳化SearchBarCreator 建構子的程式碼邏輯
五. 寫全域唯一的呼叫實例
七. 新增出現的動畫
#八.自動對焦
總結:
原始碼
首頁 web前端 Vue.js 圖文詳解Vue3實作全域搜尋框步驟(附程式碼)

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

Jan 13, 2023 pm 04:22 PM
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/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/020/659e9d144b30400682dc69d8bf2b853c-18.png" 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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱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

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

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1668
14
CakePHP 教程
1428
52
Laravel 教程
1329
25
PHP教程
1273
29
C# 教程
1256
24
Vue3如何實作刷新頁面局部內容 Vue3如何實作刷新頁面局部內容 May 26, 2023 pm 05:31 PM

想要實現頁面的局部刷新,我們只需要實現局部元件(dom)的重新渲染。在Vue中,想要實現這效果最簡單的方式方法就是使用v-if指令。在Vue2中我們除了使用v-if指令讓局部dom的重新渲染,也可以新建一個空白元件,需要刷新局部頁面時跳轉至這個空白元件頁面,然後在空白元件內的beforeRouteEnter守衛中又跳轉回原來的頁面。如下圖所示,如何在Vue3.X中實現點擊刷新按鈕實現紅框範圍內的dom重新加載,並展示對應的加載狀態。由於Vue3.X中scriptsetup語法中組件內守衛只有o

vue3專案中怎麼使用tinymce vue3專案中怎麼使用tinymce May 19, 2023 pm 08:40 PM

tinymce是一個功能齊全的富文本編輯器插件,但在vue中引入tinymce並不像別的Vue富文本插件一樣那麼順利,tinymce本身並不適配Vue,還需要引入@tinymce/tinymce-vue,並且它是國外的富文本插件,沒有透過中文版本,需要在其官網下載翻譯包(可能需要翻牆)。 1.安裝相關依賴npminstalltinymce-Snpminstall@tinymce/tinymce-vue-S2、下載中文包3.引入皮膚和漢化包在項目public資料夾下新建tinymce資料夾,將下載的

vue3+vite:src使用require動態匯入圖片報錯怎麼解決 vue3+vite:src使用require動態匯入圖片報錯怎麼解決 May 21, 2023 pm 03:16 PM

vue3+vite:src使用require動態導入圖片報錯和解決方法vue3+vite動態的導入多張圖片vue3如果使用的是typescript開發,就會出現require引入圖片報錯,requireisnotdefined不能像使用vue2這樣imgUrl:require(' …/assets/test.png')導入,是因為typescript不支援require所以用import導入,下面介紹如何解決:使用awaitimport

Vue3怎麼解析markdown並實現程式碼高亮顯示 Vue3怎麼解析markdown並實現程式碼高亮顯示 May 20, 2023 pm 04:16 PM

Vue實作部落格前端,需要實作markdown的解析,如果有程式碼則需要實作程式碼的高亮。 Vue的markdown解析函式庫很多,如markdown-it、vue-markdown-loader、marked、vue-markdown等。這些庫都大同小異。這裡選用的是marked,程式碼高亮的函式庫選用的是highlight.js。具體實現步驟如下:一、安裝依賴庫在vue專案下開啟命令窗口,並輸入以下命令npminstallmarked-save//marked用於將markdown轉換成htmlnpmins

Vue3復用元件怎麼使用 Vue3復用元件怎麼使用 May 20, 2023 pm 07:25 PM

前言無論是vue還是react,當我們遇到多處重複程式碼的時候,我們都會想著如何重複使用這些程式碼,而不是一個檔案裡充斥著一堆冗餘程式碼。實際上,vue和react都可以透過抽組件的方式來達到復用,但如果遇到一些很小的程式碼片段,你又不想抽到另外一個檔案的情況下,相比而言,react可以在相同文件裡面宣告對應的小元件,或透過renderfunction來實現,如:constDemo:FC=({msg})=>{returndemomsgis{msg}}constApp:FC=()=>{return(

Vue3中怎麼實現選取頭像並裁剪 Vue3中怎麼實現選取頭像並裁剪 May 29, 2023 am 10:22 AM

最終效果安裝VueCropper組件yarnaddvue-cropper@next上面的安裝值針對Vue3的,如果時Vue2或想使用其他的方式引用,請訪問它的npm官方地址:官方教程。在元件中引用使用時也很簡單,只需要引入對應的元件和它的樣式文件,我這裡沒有在全域引用,只在我的元件檔案中引入import{userInfoByRequest}from'../js/api' import{VueCropper}from'vue-cropper&

怎麼使用vue3+ts+axios+pinia實現無感刷新 怎麼使用vue3+ts+axios+pinia實現無感刷新 May 25, 2023 pm 03:37 PM

vue3+ts+axios+pinia實作無感刷新1.先在專案中下載aiXos和pinianpmipinia--savenpminstallaxios--save2.封裝axios請求-----下載js-cookienpmiJS-cookie-s//引入aixosimporttype{AxiosRequestConfigig ,AxiosResponse}from"axios";importaxiosfrom'axios';import{ElMess

vue3項目打包發佈到伺服器後訪問頁面顯示空白怎麼解決 vue3項目打包發佈到伺服器後訪問頁面顯示空白怎麼解決 May 17, 2023 am 08:19 AM

vue3專案打包發佈到伺服器後存取頁面顯示空白1、處理vue.config.js檔案中的publicPath處理如下:const{defineConfig}=require('@vue/cli-service')module.exports=defineConfig({publicPath :process.env.NODE_ENV==='production'?'./':'/&

See all articles