国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Vue-組件詳解

dadong / 3145人閱讀

摘要:除了監聽事件外,還可以用于組件之間的自定義事件。它僅僅作為一個直接訪問子組件的應急方案,應當避免在模板或計算屬性中使用。將和合并成,會自動去判斷是普通標簽還是組件。子組件這里的狀態綁定的是父組件的數據。

查看原文站點,更多擴展內容及更佳閱讀體驗!
組件詳解 組件與復用

Vue組件需要注冊后才可以使用。注冊有全局注冊和局部注冊兩種方式。

全局注冊

Vue.component("my-component", {});

要在父實例中使用這個組件,必須要在實例創建前注冊,之后就可以用的形式來使用組件。

Vue.component("my-component", {
    template: `
這是一個組件
` });

template的DOM結構必須被一個元素包含,缺少

會無法渲染并報錯。

在Vue實例中,使用components選項可以局部注冊組件,注冊后的組件只在該實例作用域下有效。

組件中也可以使用components選項來注冊組件,使組件可以嵌套。

var Child = {
    template: `
局部注冊組件的內容
` }; new Vue({ el: "#app", components: { "my-component": Child }, });

Vue組件的模板在某些情況下會受到HTML的限制,比如

內規定只允許是
等這些表格元素,所以在內直接使用組件時無效的。這種情況下,可以使用特殊的is屬性來掛載組件

Vue.component("my-component", { template: `
這里是組件內容
` });

常見的限制元素還有

      props: ["message"], template: `
      {{message}}
      `, data: { parentMessage: "" }

      這里用v-model綁定了父級的數據parentMessage,當通過輸入框任意輸入時,子組件接收到的props["message"]也會實時響應,并更新組件模板。

      單向數據流

      業務中會經常遇到兩種需要改變prop的情況,一種是父組件傳遞初始值進來,子組件將它作為初始值保存起來,在自己的作用域下可以隨意使用和修改。這種情況可以在組件data內再聲明一個數據,引用父組件的prop

      Vue.component("my-component", { props: ["initCount"], template: `
      {{count}}
      `, data() { return { count:this.initCount } } });

      組件中聲明了數據count,它在組件初始化時會獲取來自父組件的initCount,之后就與之無關了,只用維護count,這樣就可以避免直接操作initCount

      另一種情況就是prop作為需要被轉變的原始值傳入,這種情況用計算屬性就可以。

      Vue.component("my-component", { props: ["width"], template: `
      組件內容
      `, computed: { style: function () { return { width: this.width + "px" } } } });

      因為用CSS傳遞寬度要帶單位(px),數值計算一般不帶單位,所以統一在組件內使用計算屬性。

      在JavaScript中對象和數組時引用類型,指向同一個內存空間,所以props是對象和數組時,在子組件內改變是會影響父組件。
      數組驗證

      prop需要驗證時,需要對象寫法。

      一般當組件需要提供給別人使用時,推薦都進行數據驗證。比如某個數據必須是數字類型,如果傳入字符串,就會在控制臺彈出警告。

      Vue.component("my-component", {
          props: {
              // 必須是數字
              propA: Number,
              // 必須是字符串或數字類型
              propB: [String, Number],
              // 布爾值,如果沒有定義,默認值是true
              propC: {
                  type: Boolean,
                  default: true
              },
              // 數字,而且是必傳
              propD: {
                  type: Number,
                  default: true
              },
              // 如果是數組或對象,默認值必須是一個函數來返回
              propE: {
                  type: Array,
                  default: function () {
                      return []
                  }
              },
              // 自定義一個驗證函數
              propF: {
                  validator: function (value) {
                      return value > 10
                  }
              }
          }
      });

      驗證的type類型可以是:

      String

      Number

      Boolean

      Object

      Array

      Function

      type也可以是一個自定義構造器,使用instanceof檢測。

      組件通信

      組件關系可分為父組件通信、兄弟組件通信、跨級組件通信。

      自定義事件

      當子組件需要向父組件傳遞數據時,就要用到自定義事件。

      v-on除了監聽DOM事件外,還可以用于組件之間的自定義事件。

      JavaScript的設計模式——觀察者模式方法:

      dispatchEvent

      addEventListener

      Vue組件的子組件用$emit()來觸發事件,父組件用$on()來監聽子組件的事件。

      父組件也可以直接在子組件的自定義標簽上使用v-on來監聽子組件觸發的自定義事件。

      總數:{{total}}

      Vue.component("my-component", { template: `
      `, data() { return { counter: 0 } }, methods: { handleIncrease: function () { this.counter++; this.$emit("increase", this.counter); }, handlereduce: function () { this.counter--; this.$emit("reduce", this.counter) } } }); new Vue({ el: "#app", data: { total: 0 }, methods: { handleGetTotal: function (total) { this.total = total; } } });

      在改變組件的data "counter"后,通過$emit()再把它傳遞給父組件,父組件用@increase@reduce$emit()方法的第一個參數是自定義事件的名稱。

      除了用v-on在組件上監聽自定義事件外,也可以監聽DOM事件,這時可以用.native修飾符表示監聽時一個原生事件,監聽的是該組件的根元素。

      
      
      使用v-model

      Vue可以在自定義組件上使用v-model指令。

      
      

      組件$emit()的事件名時特殊的input,在使用組件的父級,并沒有在上使用@input="handler",而是直接用了v-model綁定的一個數據total

      
      

      v-model還可以用來創建自定義的表單輸入組件,進行數據雙向綁定。

      總數:{{total}}

      Vue.component("my-component", { props: ["value"], template: ``, methods: { updateValue: function () { this.$emit("input", event.target.value) } } }); new Vue({ el: "#app", data: { total: 10 }, methods: { handleReduce: function () { this.total--; } } });

      實現這樣一個具有雙向綁定的v-model組件要滿足下面兩個要求:

      接收一個value屬性

      在有新的value時觸發input事件

      非父子組件通信

      在實際業務中,除了父子組件通信外,還有很多非父子組件通信的場景,非父子組件一般有兩種,兄弟組件跨多級組件

      Vue 1.x版本中,除了$emit()方法外,還提供了¥dispatch()$broadcast()

      $dispatch()用于向上級派發事件,只要是它的父級(一級或多級以上),都可以在Vue實例的events選項內接收。

      此實例只在Vue 1.x版本中有效:

      {{message}}

      Vue.component("my-component", { template: ``, methods: { handleDispatch: function () { this.$dispatch("on-message", "來自內部組件的數據") } } }); new Vue({ el: "#app", data: { message: "" }, events: { "on-message": function (msg) { this.message = msg; } } });

      $broadcast()是由上級向下級廣播事件,用法完全一致,方向相反。

      這兩種方法一旦發出事件后,任何組件都可以接收到,就近原則,而且會在第一次接收到后停止冒泡,除非返回true

      這些方法在Vue 2.x版本中已廢棄。

      在Vue 2.x中,推薦任何一個空的Vue實例作為中央事件總線(bus),也就是一個中介。

      {{message}}

      var bus = new Vue(); Vue.component("component-a", { template: ``, methods: { handleEvent: function () { bus.$emit("on-message", "來自組件component-a的內容") } } }); var app = new Vue({ el: "#app", data: { message: "" }, mounted: function () { var _this = this; // 在實例初始化時,監聽來自bus實例的事件 bus.$on("on-message", function (msg) { _this.message = msg; }) } });

      首先創建了一個名為bus的空的Vue實例;然后全局定義了組件component-a;最后創建了Vue實例app

      app初始化時,也就是在生命周期mounted鉤子函數里監聽了來自bus的事件on-message,而在組件component-a中,點擊按鈕后會通過bus把事件on-message發出去。此時app就會接收到來自bus的事件,進而在回調里完成自己的業務邏輯。

      這種方法巧妙而輕量地實現了任何組件間的通信,包括父子、兄弟、跨級。

      如果深入使用,可以擴展bus實例,給它添加datamethodscomputed等選項,這些都是可以公用的。

      在業務中,尤其是協同開發時非常有用,因為經常需要共享一些通用的信息,比如用戶登錄的昵稱、性別、郵箱等,還有用戶的授權token等。

      只需在初始化時讓bus獲取一次,任何時間、任何組件就可以從中直接使用,在單頁面富應用(SPA)中會很實用。

      除了中央事件總線bus外,還有兩種方法可以實現組件間通信:父鏈和子組件索引。

      父鏈

      在子組件中,使用this.$parent可以直接訪問該組件的父實例或組件,父組件也可以通過this.$children訪問它所有的子組件,而且可以遞歸向上或向下無限訪問,直到根實例或最內層的組件。

      {{message}}

      Vue.component("component-a", { template: ``, methods: { handleEvent: function () { this.$parent.message = "來自組件component-a的內容" } } }); var app = new Vue({ el: "#app", data: { message: "" } });

      盡管Vue允許這樣操作,但在業務中,子組件應該盡可能地避免依賴父組件的數據,更不應該去主動修改它的數據,因為這樣使得父子組件緊耦合,只看父組件,很難理解父組件的狀態,因為它可能被任意組件修改,理想狀態下,只有組件自己能修改它的狀態。

      父子組件最好還是通過props$emit()來通信。

      子組件索引

      當子組件較多時,通過this.$children來遍歷出需要的一個組件實例是比較困難的,尤其是組件動態渲染時,它們的序列是不固定的。

      Vue提供了子組件索引的方法,用特殊的屬性ref來為子組件指定一個索引名稱。

      Vue.component("component-a", { template: `
      子組件
      `, data() { return { message: "子組件內容" } }, }); var app = new Vue({ el: "#app", methods: { handleRef: function () { // 通過$refs來訪問指定的實例 var msg = this.$refs.comA.message; console.log(msg); } } });

      在父組件模板中,子組件標簽上使用ref指定一個名稱,并在父組件內通過this.$refs來訪問指定名稱的子組件。

      $refs只在組件渲染完成后才填充,并且它是非響應式的。它僅僅作為一個直接訪問子組件的應急方案,應當避免在模板或計算屬性中使用$refs

      Vue 2.x將v-elv-ref合并成ref,Vue會自動去判斷是普通標簽還是組件。

      使用slot分發內容

      當需要讓組件組合使用,混合父組件的內容與子組件的模板時,就會用到slot,這個過程叫做內容分發

      組件不知道它的掛載點會有什么內容。掛載點的內容是由的父組件決定的。

      組件很可能有它自己的模板。

      props傳遞數據、events觸發事件和slot內容分發就構成了Vue組件的3個API來源,再復雜的組件也是由這3部分構成。

      作用域

      父組件中的模板:

      
          {{message}}
      
      

      這里的message就是一個slot,但是它綁定的是父組件的數據,而不是組件的數據。

      父組件模板的內容是在父組件作用域內編譯,子組件模板的內容是在子組件作用域內編譯。

      Vue.component("child-component", { template: `
      子組件1
      `, }); var app = new Vue({ el: "#app", data: { showChild: true } });

      這里的狀態showChild綁定的是父組件的數據。

      在子組件上綁定數據:

      Vue.component("child-component", { template: `
      子組件
      `, data() { return { showChild: true } } }); var app = new Vue({ el: "#app", });

      因此,slot分發的內容,作用域是在父組件上

      單個slot

      在子組件內使用特殊的元素就可以為這個組件開啟一個slot(插槽),在父組件模板里,插入在子組件標簽內的所有內容將替代子組件的標簽及它的內容。

      分發的內容

      更多分發的內容

      Vue.component("child-component", { template: `

      如果沒有父組件插入內容,我將作為默認出現。

      `, }); var app = new Vue({ el: "#app", });

      子組件child-component的模板內定義了一個元素,并且用一個

      作為默認的內容,在父組件沒有使用slot時,會渲染這段默認的文本;如果寫入了slot,就會替換整個

      子組件內的備用內容,它的作用域是子組件本身。
      具名Slot

      元素指定一個name后可以分發多個內容,具名slot可以與單個slot共存。

      標題

      正文的內容

      更多正文的內容

      底部信息
      Vue.component("child-component", { template: `
      `, }); var app = new Vue({ el: "#app", });

      子組件內聲明了3個元素,其中在

      內的沒有使用name特性,它將作為默認slot出現,父組件沒有使用slot特性的元素與內容都將出現在這里。

      如果沒有指定默認的匿名slot,父組件內多余的內容都將被拋棄。

      在組合使用組件時,內容分發API至關重要。

      作用域插槽

      作用域插槽是一種特殊的slot,使用一個可以復用的模板替換已渲染元素。

      Vue.component("child-component", { template: `
      `, }); var app = new Vue({ el: "#app", });

      子組件的模板,在元素上有一個類似props傳遞數據給組件的寫法msg="xxx",將數據傳遞到插槽。

      父組件中使用了