成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Vue-組件詳解

dadong / 3161人閱讀

摘要:除了監(jiān)聽事件外,還可以用于組件之間的自定義事件。它僅僅作為一個(gè)直接訪問子組件的應(yīng)急方案,應(yīng)當(dāng)避免在模板或計(jì)算屬性中使用。將和合并成,會(huì)自動(dòng)去判斷是普通標(biāo)簽還是組件。子組件這里的狀態(tài)綁定的是父組件的數(shù)據(jù)。

查看原文站點(diǎn),更多擴(kuò)展內(nèi)容及更佳閱讀體驗(yàn)!
組件詳解 組件與復(fù)用

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

全局注冊

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

要在父實(shí)例中使用這個(gè)組件,必須要在實(shí)例創(chuàng)建前注冊,之后就可以用的形式來使用組件。

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

template的DOM結(jié)構(gòu)必須被一個(gè)元素包含,缺少

會(huì)無法渲染并報(bào)錯(cuò)。

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

組件中也可以使用components選項(xiàng)來注冊組件,使組件可以嵌套。

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

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

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

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

常見的限制元素還有

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

      這里用v-model綁定了父級的數(shù)據(jù)parentMessage,當(dāng)通過輸入框任意輸入時(shí),子組件接收到的props["message"]也會(huì)實(shí)時(shí)響應(yīng),并更新組件模板。

      單向數(shù)據(jù)流

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

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

      組件中聲明了數(shù)據(jù)count,它在組件初始化時(shí)會(huì)獲取來自父組件的initCount,之后就與之無關(guān)了,只用維護(hù)count,這樣就可以避免直接操作initCount

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

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

      因?yàn)橛肅SS傳遞寬度要帶單位(px),數(shù)值計(jì)算一般不帶單位,所以統(tǒng)一在組件內(nèi)使用計(jì)算屬性。

      在JavaScript中對象和數(shù)組時(shí)引用類型,指向同一個(gè)內(nèi)存空間,所以props是對象和數(shù)組時(shí),在子組件內(nèi)改變是會(huì)影響父組件。
      數(shù)組驗(yàn)證

      當(dāng)prop需要驗(yàn)證時(shí),需要對象寫法。

      一般當(dāng)組件需要提供給別人使用時(shí),推薦都進(jìn)行數(shù)據(jù)驗(yàn)證。比如某個(gè)數(shù)據(jù)必須是數(shù)字類型,如果傳入字符串,就會(huì)在控制臺彈出警告。

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

      驗(yàn)證的type類型可以是:

      String

      Number

      Boolean

      Object

      Array

      Function

      type也可以是一個(gè)自定義構(gòu)造器,使用instanceof檢測。

      組件通信

      組件關(guān)系可分為父組件通信、兄弟組件通信、跨級組件通信。

      自定義事件

      當(dāng)子組件需要向父組件傳遞數(shù)據(jù)時(shí),就要用到自定義事件。

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

      JavaScript的設(shè)計(jì)模式——觀察者模式方法:

      dispatchEvent

      addEventListener

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

      父組件也可以直接在子組件的自定義標(biāo)簽上使用v-on來監(jiān)聽子組件觸發(fā)的自定義事件。

      總數(shù):{{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()方法的第一個(gè)參數(shù)是自定義事件的名稱。

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

      
      
      使用v-model

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

      
      

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

      
      

      v-model還可以用來創(chuàng)建自定義的表單輸入組件,進(jìn)行數(shù)據(jù)雙向綁定。

      總數(shù):{{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--; } } });

      實(shí)現(xiàn)這樣一個(gè)具有雙向綁定的v-model組件要滿足下面兩個(gè)要求:

      接收一個(gè)value屬性

      在有新的value時(shí)觸發(fā)input事件

      非父子組件通信

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

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

      $dispatch()用于向上級派發(fā)事件,只要是它的父級(一級或多級以上),都可以在Vue實(shí)例的events選項(xiàng)內(nèi)接收。

      此實(shí)例只在Vue 1.x版本中有效:

      {{message}}

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

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

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

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

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

      {{message}}

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

      首先創(chuàng)建了一個(gè)名為bus的空的Vue實(shí)例;然后全局定義了組件component-a;最后創(chuàng)建了Vue實(shí)例app。

      app初始化時(shí),也就是在生命周期mounted鉤子函數(shù)里監(jiān)聽了來自bus的事件on-message,而在組件component-a中,點(diǎn)擊按鈕后會(huì)通過bus把事件on-message發(fā)出去。此時(shí)app就會(huì)接收到來自bus的事件,進(jìn)而在回調(diào)里完成自己的業(yè)務(wù)邏輯。

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

      如果深入使用,可以擴(kuò)展bus實(shí)例,給它添加datamethods、computed等選項(xiàng),這些都是可以公用的。

      在業(yè)務(wù)中,尤其是協(xié)同開發(fā)時(shí)非常有用,因?yàn)榻?jīng)常需要共享一些通用的信息,比如用戶登錄的昵稱、性別、郵箱等,還有用戶的授權(quán)token等。

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

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

      父鏈

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

      {{message}}

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

      盡管Vue允許這樣操作,但在業(yè)務(wù)中,子組件應(yīng)該盡可能地避免依賴父組件的數(shù)據(jù),更不應(yīng)該去主動(dòng)修改它的數(shù)據(jù),因?yàn)檫@樣使得父子組件緊耦合,只看父組件,很難理解父組件的狀態(tài),因?yàn)樗赡鼙蝗我饨M件修改,理想狀態(tài)下,只有組件自己能修改它的狀態(tài)。

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

      子組件索引

      當(dāng)子組件較多時(shí),通過this.$children來遍歷出需要的一個(gè)組件實(shí)例是比較困難的,尤其是組件動(dòng)態(tài)渲染時(shí),它們的序列是不固定的。

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

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

      在父組件模板中,子組件標(biāo)簽上使用ref指定一個(gè)名稱,并在父組件內(nèi)通過this.$refs來訪問指定名稱的子組件。

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

      Vue 2.x將v-elv-ref合并成ref,Vue會(huì)自動(dòng)去判斷是普通標(biāo)簽還是組件。

      使用slot分發(fā)內(nèi)容

      當(dāng)需要讓組件組合使用,混合父組件的內(nèi)容與子組件的模板時(shí),就會(huì)用到slot,這個(gè)過程叫做內(nèi)容分發(fā)。

      組件不知道它的掛載點(diǎn)會(huì)有什么內(nèi)容。掛載點(diǎn)的內(nèi)容是由的父組件決定的。

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

      props傳遞數(shù)據(jù)、events觸發(fā)事件和slot內(nèi)容分發(fā)就構(gòu)成了Vue組件的3個(gè)API來源,再復(fù)雜的組件也是由這3部分構(gòu)成。

      作用域

      父組件中的模板:

      
          {{message}}
      
      

      這里的message就是一個(gè)slot,但是它綁定的是父組件的數(shù)據(jù),而不是組件的數(shù)據(jù)。

      父組件模板的內(nèi)容是在父組件作用域內(nèi)編譯,子組件模板的內(nèi)容是在子組件作用域內(nèi)編譯。

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

      這里的狀態(tài)showChild綁定的是父組件的數(shù)據(jù)。

      在子組件上綁定數(shù)據(jù):

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

      因此,slot分發(fā)的內(nèi)容,作用域是在父組件上。

      單個(gè)slot

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

      分發(fā)的內(nèi)容

      更多分發(fā)的內(nèi)容

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

      如果沒有父組件插入內(nèi)容,我將作為默認(rèn)出現(xiàn)。

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

      子組件child-component的模板內(nèi)定義了一個(gè)元素,并且用一個(gè)

      作為默認(rèn)的內(nèi)容,在父組件沒有使用slot時(shí),會(huì)渲染這段默認(rèn)的文本;如果寫入了slot,就會(huì)替換整個(gè)。

      子組件內(nèi)的備用內(nèi)容,它的作用域是子組件本身。
      具名Slot

      元素指定一個(gè)name后可以分發(fā)多個(gè)內(nèi)容,具名slot可以與單個(gè)slot共存。

      標(biāo)題

      正文的內(nèi)容

      更多正文的內(nèi)容

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

      子組件內(nèi)聲明了3個(gè)元素,其中在

      內(nèi)的沒有使用name特性,它將作為默認(rèn)slot出現(xiàn),父組件沒有使用slot特性的元素與內(nèi)容都將出現(xiàn)在這里。

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

      在組合使用組件時(shí),內(nèi)容分發(fā)API至關(guān)重要。

      作用域插槽

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

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

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

      父組件中使用了