組件使用v-model、$listeners、.sync(區別於v-model的雙向數據綁定)

来源:https://www.cnblogs.com/liuyilong/archive/2020/01/19/12215583.html
-Advertisement-
Play Games

自定義組件 1. 自定義組件的v model 首先我們先說一下在自定義組件中使用v model的必要條件 在自定義的組件中要有input(這裡我們先不討論單選覆選框) 在自定義組件的模板對象中要有props屬性,且裡面要含有一個value 在自定義組件的input標簽上要綁定value屬性值為pro ...


自定義組件

  1. 自定義組件的v-model

    首先我們先說一下在自定義組件中使用v-model的必要條件

    • 在自定義的組件中要有input(這裡我們先不討論單選覆選框)
    • 在自定義組件的模板對象中要有props屬性,且裡面要含有一個value
    • 在自定義組件的input標簽上要綁定value屬性值為props中傳入的值,且還需要發出一個input事件

    這樣講可能會有點難理解,還是上代碼吧...

    <div id="app">
      <child-com v-model="message"></child-com>
      <span>{{ message }}</span>
    </div>
    <template id="childCom">
      <div>
        <input type="text" :value="value" @input='inputEvent'>
      </div>
    </template>
    
    <script>
      const childCom = {
        template: '#childCom',
        props: ['value'],
        methods: {
          inputEvent(event) {
            this.$emit('aaa', event.target.value)
          }
        },
      }
    
      const vm = new Vue({
        el: '#app',
        data: {
          message: '可以雙向綁定的了'
        },
        components: {
          childCom
        }
      })
    </script>

    這是最終實現效果需要必備的,看完這些代碼如果你是小白,你可能會有點不理解為什麼要這樣做,下麵我告訴你原理。

    首先在我們使用的v-model 中,其內部實現的原理就是一個 value屬性和一個input事件,其主要步驟就是,用v-bind綁定value,然後用input事件監聽值的變化,當文本框中的值發生變化的時候,input事件就會觸發,那麼我們可以在input事件中獲取到改變後的值然後賦值給value,這樣是不是就完成了雙向數據綁定了。上代碼:

    <div id="app">
      <input type='text' :value='message' @input='inputEvent'>
      <span>{{ message }}</span>
    </div>
    
    <script>
      const vm = new Vue({
        el: '#app',
        data: {
          message: '可以雙向綁定的了'
        },
        methods: {
          inputEvent(event) {
            this.message = event.target.value;
          }
        }
      })
    </script>

    就這樣幾個步驟,就達到了v-model的效果了,這就是他的原理,然後讓我們深一步想,讓自定義組件使用雙向數據綁定。因為我們知道其內部就是value和input事件,

    所以有瞭如下代碼:

    <div id="app">
        <child-com :value='message' @input='message=$event'></child-com> <!-- 此代碼就這裡和最開始代碼不同 -->
        <span>{{ message }}</span>
      </div>
    
      <template id="childCom">
        <div>
          <input type="text" :value="value" @input='inputEvent'>
        </div>
      </template>
    
      <script>
        const childCom = {
          template: '#childCom',
          props: ['value'],
          methods: {
            inputEvent(event) {
              this.$emit('input', event.target.value)
            }
          },
        }
    
        const vm = new Vue({
          el: '#app',
          data: {
            message: '可以雙向綁定的了'
          },
          components: {
            childCom
          }
        })
    </script>

    根據上面的原理,現在你應該知道了為什麼要傳一個value在子組件了吧,明白之後,您就可以把 <child-com :value='message' @input='message=$event'></child-com> 替換成 <child-com v-model="message"></child-com> 了。

  2. $listeners的使用

    由來:當我們在項目開發過程中會出現很多組件嵌套的關係,那麼如果還要在最外層的組件向內部傳遞數據的話,有如下幾種方式:

    • 從父向子傳遞,子再向孫傳遞,一直傳遞下去,那麼最裡面的組件想往最外層傳東西則可以從最裡面向外面逐層$emit發送出去,但是仔細想想,一個簡單的傳遞信息,卻涉及到了這之間所有的組件,而他們只是一個中間者,這讓代碼維護起來非常困難
    • 使用vuex來進行傳遞,這樣確實方便了很多,但是這樣做如果沒有其他用處的話就有點大材小用了
    • 使用事件匯流排,這樣使用也不容易維護

    $listeners$attrs 的出現,就完美的解決了第一種情況的發生

    <div id="app">
        <child-com :name='name' :age='age' @test-listeners='testListeners'></child-com>
      </div>
    
      <script>
        const vm = new Vue({
          el: '#app', //  父組件
          data: {
            name: 'lyl',
            age: 20,
          },
          methods: {
            testListeners(arg) {
              console.log(arg)
            }
          },
          components: {
            childCom: { //  子組件
              inheritAttrs: false,
              template: `
                <div>
                  <span> {{name}} </span>
                  <grand-com v-bind='$attrs' v-on='$listeners'></grand-com>
                </div>
              `,
              props: ['name'],
              components: {
                grandCom: { //  孫子組件
                  inheritAttrs: false,
                  template: `
                    <div>
                      <span @click='listenClick'>{{$attrs.age}}</span>
                    </div>
                  `,
                  methods: {
                    listenClick() {
                      this.$emit('test-listeners','aaaaaaa');
                    }
                  },
                }
              }
            }
          }
        })
    </script>

    上面代碼中,孫子組件要發出一個是將讓父組件調用,這個時候我們可以在中間過渡的子組件模板使用的孫子組件上綁定這個屬性,即:v-on='$listeners',這樣一來父組件就能直接調用孫子組件發出的方法了,並且在中間層的子組件上並沒有什麼多餘的部分

  3. .sync的使用方法

    我們都知道,在一個組件上,我們只能使用一個v-model,但是如果我們的組件中有多個input標簽呢,並且每個input標簽中的值都不同,且每個都想進行雙向綁定,這個時候,v-model就不行了。於是乎就出現了.sync的出現。

    根據上面我說的那些需求,我們寫一下代碼:

    • 不使用.sync的代碼
    <div id="app">
        <child-com 
          :value='obj.value' @aaa='obj.value = $event'
          :name='obj.name'  @bbb='obj.name = $event'
          :age='obj.age' @ccc='obj.age = $event'>
        </child-com>
    
        <p>{{ obj }}</p>
        <p>{{ obj.value }}</p>
        <p>{{ obj.name }}</p>
        <p>{{ obj.age }}</p>
      </div>
    
    <!-- childCom組件的模板 -->
      <template id="childCom">
        <div>
          <input type="text" :value="value" @input='inputValueEvent'>
          <br>
          <input type="text" :value="name" @input='inputNameEvent'>
          <br>
          <input type="text" :value="age" @input='inputAgeEvent'>
        </div>
      </template>
    
      <script>
        const childCom = {
          template: '#childCom',
          props: ['value','name','age'],
          methods: {
            inputValueEvent(event) {
              this.$emit('aaa', event.target.value)
            },
            inputNameEvent(event) {
              this.$emit('bbb', event.target.value)
            },
            inputAgeEvent(event) {
              this.$emit('ccc', event.target.value)
            }
          },
        }
    
        const vm = new Vue({
          el: '#app',
          data: {
            obj: { value: '雙向綁定' , name: 'coderlyl' , age: 20}
          },
          components: {
            childCom
          }
        })
    </script>

    根據上面的代碼,我們不難發現,我們在標簽中書寫了過多的重覆的東西,可讀性也不是很好,下麵我們再使用 .sync 的方式

    • 使用.sync的代碼
    <div id="app">
        <child-com v-bind:value.sync='obj.value' 
                   v-bind:name.sync="obj.name" 
                   v-bind:age.sync="obj.age">    <!--這裡也發生了變化-->
        </child-com>
    
        <p>{{ obj }}</p>
        <p>{{ obj.value }}</p>
        <p>{{ obj.name }}</p>
        <p>{{ obj.age }}</p>
      </div>
      <template id="childCom">
        <div>
          <input type="text" :value="value" @input='inputValueEvent'>
          <br>
          <input type="text" :value="name" @input='inputNameEvent'>
          <br>
          <input type="text" :value="age" @input='inputAgeEvent'>
        </div>
      </template>
    
      <script>
        const childCom = {
          template: '#childCom',
          props: ['value','name','age'],
          methods: {
            inputValueEvent(event) {
              this.$emit('update:value', event.target.value) // 這裡發生了變化
            },
            inputNameEvent(event) {
              this.$emit('update:name', event.target.value) // 這裡發生了變化
            },
            inputAgeEvent(event) {
              this.$emit('update:age', event.target.value) // 這裡發生了變化
            }
          },
        }
    
        const vm = new Vue({
          el: '#app',
          data: {
            message: '可以雙向綁定的了',
            obj: { value: '雙向綁定' , name: 'coderlyl' , age: 20}
          },
          components: {
            childCom
          }
        })
    </script>

    也許看完這裡,你並沒有覺得好到哪裡去了,下麵還有更簡單的寫法

    <child-com v-bind.sync="obj"></child-com>
    <!-- 其他代碼一樣 -->

    對,沒錯!這是終極簡化版,但是這隻針對於對象才能用

    註意帶有 .sync 修飾符的 v-bind 不能和表達式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是無效的)。取而代之的是,你只能提供你想要綁定的屬性名,類似 v-model

    v-bind.sync 用在一個字面量的對象上,例如 v-bind.sync=”{ title: doc.title }”,是無法正常工作的,因為在解析一個像這樣的複雜表達式的時候,有很多邊緣情況需要考慮。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 參考:https://www.postgresql.org/docs/current/install-procedure.html 完事開頭難!!!如果想瞭解一門技術,看文檔必不可少,實操更不可少,這篇博文記錄了自己學習postgesql的測試安裝文檔,由於對pg的參數瞭解甚少,目前使用的預設的參數 ...
  • postgresql 作為官方號稱的最先進的開源資料庫,從今天(2020-1-19)起開始系統的學習一下,記錄自己學習的點點滴滴。 ...
  • 一幅畫,一次瞬間的回眸,就在那次畫展上,那個眼神,溫柔的流轉,還是那乾凈的皮鞋,一塵不染,俊朗的眉宇性感的唇,悄悄走近,牽手一段浪漫 [toc] MySQL筆記(二) 13、條件查詢 1.普通條件查詢 語法:SELECT COL_LIST FROM TABLE_NAME [WHERE CONDITI ...
  • 每天給自己一個希望,努力做好自己,不為明天煩惱,不為昨天嘆息。當夢想還在,告訴自己:努力,就總能遇見更好的自己! [toc] MySql筆記(一) 1、創建資料庫以及刪除 1.創建資料庫語法:(命令行視窗操作) ~~~~sql CREATE DATABASE DATABASENAME ~~~~ 示例 ...
  • 關於非同步消息,大家都知道,如下: 這些用起來都是比較複雜的,RabbitMQ先要創建Exchange,在創建Queue,還要將Queue和Exchange通過某種規則綁定起來。發消息之前要指定routing-Key,還要控制頭部信息。 即使你只需要一組消息者。那麼你就要經歷上面繁瑣的過程。 但是Re ...
  • 準備工作 因為在編譯時需要下載許多依賴包,在執行編譯前最好先配置下代理倉庫 編譯flink shaded 因為flink依賴flink shaded工程,基本的依賴項都是在這個工程裡面定義的,所以要先編譯這個工程 1. 下載flink shaded工程 "flink shaded" 1. 在寫文章時 ...
  • 在Vue進行前端開發中,表單的輸入是基礎且常見的功能,本文以一個簡單的小例子,簡述v-model數據綁定的用法,僅供學習分享使用,如有不足,還請指正。 ...
  • 插槽 1. 具名插槽 自 2.6.0 起有所更新。已廢棄的使用 attribute 的語法 但是我們有了新的語法,如下: 子組件 childCom: 父組件 app: 效果圖: 註意: 只能添加在 上 2. 作用域插槽 有時讓插槽內容能夠訪問子組件中才有的數據是很有用的。但是由於子組件的作用域在子組 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...