iT邦幫忙

2021 iThome 鐵人賽

DAY 23
0
Modern Web

Vue.js 什麼意思系列 第 23

Day 23:兒子有事交給爸-$emit 傳出事件

透過 Props 可以讓子元件接收來自父元件的「資料」,相對地,父元件則可以接收來自子元件的「事件」,雙方互相傳遞內容,最終可讓子元件變成單純處理畫面樣式的 pure component,而父元件則掌握所有控制權,再次以集中管理的方式讓複雜程序的執行侷限在父元件身上,同時也能加速除錯時不用反覆查找資料出錯的位置。

那麼就來嘗試應用在解決新需求上,首先需要在頁面內新增一個搜尋欄,不同於 Navbar 針對全站的關鍵字查詢功能(預先假設),該搜尋欄位只會針對頁面資料範圍內的書本名稱進行比對。

vm.$emit( eventName, […args] ):定義需要接收來自子元件的事件

  • 先在子元件使用 v-on 監聽事件,並定義好事件名稱 searchBook 及所需傳遞的參數 $event,再將事件 $emit 傳給父元件。

    <div class="BookList">
        <h1>{{ navTitle }}</h1>
        <p>共計 {{ bookList.length }} 本書</p>
        <label>搜尋書本:
            <input
                type="text"
                :value="inputText"
                @input="$emit('searchBook', $event)" />
        </label>
        <div class="bookshelf">
            <!-- 略 -->
        </div>
    </div>
    

    input 需要顯示的 value 值則再次透過 prop 取自於父元件傳入的資料。

    props: {
        inputText: {
            type: String,
            required: false,
        },
    },
    
  • 在父元件監聽該事件名稱 searchText,獲得即時輸入的結果為 $event.target.value,因為沒有需要執行其他動作,因此直接在 <template> 將結果賦值給 inputText,讓其透過 prop 傳入子元件中的 input 顯示出來。

    <BookList
    	navTitle="All"
    	:bookList="books"
    	:inputText="searchText"
    	@searchBook="searchText = $event.target.value"
    />
    

    接著可透過簡單的正規表達式進行比對,從原本的 API 書單資料中篩選出符合搜尋欄位輸入值的書本名稱,books 陣列資料因此經過變動,而 inputText 則因為動態綁定而能同步更新資料再傳入到子元件中。

    computed: {
        books() {
            const regex = new RegExp(this.searchText, "gi");
            return this.$store.getters["allBooks"].filter((book) =>
                book.name.match(regex)
            );
        },
    },
    

試著在全部書單頁面中搜尋書本名包含「IT邦」的列表,根據輸入值即時判斷書單結果;循序漸進地先輸入「IT」兩個字,即時出現書單變化。
search IT

最後搜尋「IT邦」顯示共有 19 本書。
search IThelp

與 IT邦幫忙的導覽項目頁面結果相符,正確無誤!
IThelp page

參考資料


上一篇
Day 22:兒子乖聽爸的話-Props 傳入資料
下一篇
Day 24:路由搜查隊-route.query
系列文
Vue.js 什麼意思30

尚未有邦友留言

立即登入留言