1. 程式人生 > >Vue.js學習記錄-5-Vue進階:元件

Vue.js學習記錄-5-Vue進階:元件

6.元件 - 計數器Demo為例

  • 元件使用細節

    • 全域性元件 and 區域性元件

      全域性元件:

        	// 全域性元件(子元件)
            Vue.component('row', {
                template: '<tr><td>{{ content }}</td></tr>',
                // 2. 子元件中的data必須是函式方法形式返回唯一的資料物件
                data: function () {
                    return {
                        content: 'this is content'
                    }
                }
            }),
      

      區域性元件: 在根元件中需要宣告區域性元件

        	var counter = {
        		template: '<tr><td>{{ content }}</td></tr>',
                // 2. 子元件中的data必須是函式方法形式返回唯一的資料物件
                data: function () {
                    return {
                        content: 'this is content'
                    }
                }
        	}
      
        	var vm = new Vue({
                el: "#root",
                // 宣告區域性元件
                components: {
                    counter: counter
                },
        	)}
      
    • 元件複用:元件進行任意次數的複用

        	<!-- 計數器Demo -->
            <counter @change="handleChange" ref="one"></counter>
            <counter @change="handleChange" ref="two"></counter>
      
    • 元件中 data 必須是一個函式,每個元件例項可以維護一份被返回物件的獨立拷貝。

  • 父子元件傳值

  • 父元件通過屬性props向子元件進行傳值

     	<div id="root">
             <!-- 父元件通過屬性向子元件進行傳值 -->
             <counter :count="0" @inc="handleIncrease"></counter>
             <counter :count="0" @inc="handleIncrease"></counter>
             <div>{{ total }}</div>
     	</div>
    
     **可以看出,上述程式碼通過:count,綁定了count屬性,並添加了@inc自定義事件。**
    
     父元件(根元件)通過**:count**,對子元件進行傳值。此時,子元件通過**props**對父元件傳值進行獲取。
    
     	// 定義區域性元件
         var counter = {
             // 子元件通過props獲取父元件傳過來的值。注意:子元件不可直接對props中的資料進行更改,單向資料流原理。
             props: ['count'],
             // 對父元件傳遞過來的值,子元件進行備份後進行更改
             data: function () {
                 return {
                     number: this.count
                 }
             },
             // 下文待填充
         }
    
  • 子元件通過事件$emit向父元件進行傳值

     通過上述操作,子元件可以對父元件的資料進行**獲取**,並由於**單項資料流原理進行了備份**。
     
     接下來,**根據備份的父元件資料number進行模板渲染**。
    
     	template: "<div @click='handleCilck'>{{ number }}</div>",
    
     此時,在子元件渲染的\<div>中添加了**click事件**,當塊級元素被點選時,向父元件進行傳值。
    
     	methods: {
             handleCilck: function () {
                 this.number ++
                 // 向父元件傳遞已更改的值,觸發事件
                 this.$emit('inc', 1)
             }
         }
     點選該塊級元素時,**備份資料number執行自增操作**,之後,**通過$emit方法進行自定義事件inc宣告,以及引數傳遞**。
    
     上述提到的**@inc="handleIncrease"**,在父元件接收子元件的觸發事件,並獲取事件攜帶引數。
    
     	var vm = new Vue({
             el: "#root",
             // 宣告區域性元件
             components: {
                 counter: counter
             },
             data: {
                 total: 0
             },
             methods: {
                 // 接收子元件觸發事件,獲取事件攜帶引數
                 handleIncrease: function (step) {
                     this.total += step
                 }
             }
         })
     **自定義方法inc**所對應的 **handleIncrease** 方法觸發後,**響應式更新資料 total 的值**。
    
  • 元件的引數校驗與非Props特性

    • Prop驗證:元件的 prop 指定驗證要求,對格式、長度等方面進行引數驗證。

        <child content="hello "></child>
      

      子元件中新增Prop驗證:

        Vue.component('child', {
            props: {
                content :{
                    // 型別驗證,陣列可包含多個數據型別
                    type: [String, Number],
        			// 是否必需
                    required: false,
        			// 預設值
                    default: 'default value',
        			// 引數長度判斷
                    validator: function (value) {
                        return (value.length > 5)
                    }
                }
            },
            template: '<div>{{content}}</div>',
        })
      
    • Props特性和非Props特性

      Props特性:常規配置,父元件傳值、子元件接值、DOM內直接使用。 在這裡插入圖片描述 非Pros特性:

        1. 子元件未通過props接收,因此不能顯示在DOM上。
        2. 子元件模板內直接寫入內容而非插值表示式,會顯示在DOM最外層標籤上。
      

    在這裡插入圖片描述

  • 元件繫結原生事件

    在元件的根元素上直接進行原生事件的監聽,此時可以使用v-on的.native修飾符

      <div id="root">
      	<!-- 子元件中繫結原生的點選事件 -->
          <child @click.native="handleCilck"></child>
      </div>
    
      <script>
          Vue.component('child', {
              template: '<div>Child</div>'
          })
    
          var vm = new Vue({
              el: "#root",
              methods: {
                  handleCilck: function () {
                      alert("元件繫結原生事件")
                  }
              }
          })
      </script>
    
  • 非父子元件間傳值(Bus/匯流排/釋出訂閱模式/觀察者模式)

    業務場景如下,圖片取自Vue.js官網文件,非父子元件進行傳值的幾種形式。 在這裡插入圖片描述

    舉例: 兄弟元件之間的傳值問題,頁面如下:

      <div id="root">
          <child content="Tom"></child>
          <child content="Jerry"></child>
      </div>
    

    元件中的設定:

      // 對Vue中prototype的bus屬性新增vue例項
      Vue.prototype.bus = new Vue()
    
      // 全域性元件
      Vue.component('child', {
          // 元件模板
          template: "<div @click='handleClick'>{{selfContent}}</div>",
          // 父元件通過props進行資料傳遞
          props: {
              content: {
                  // 資料傳遞約束
                  type: String,
                  required: true
              }
          },
          // 應對單項資料流問題,建立資料副本
          data: function () {
              return {
                  selfContent: this.content
              }
          },
          methods: {
              handleClick: function () {
                  // 由於bus屬性是一個vue例項,因此可以使用$emit進行事件的宣告,攜帶引數,當前資料副本
                  this.bus.$emit('change',  this.selfContent)
              }
          },
          // 生命週期鉤子函式
          mounted() {
              // 防止this作用域發生變化,建立儲存副本
              var this_ = this
      		// 使用$on進行自定義事件change的處理
              this.bus.$on('change', function (msg) {
                  this_.selfContent = msg
              })
          },
      })	
    

    TIPS:採用 $emit 和 $on 實現非父子元件的傳值操作,需要注意的是:$emit 和 $on 事件必須在一個公共例項上,才能觸發。(本例中,公共例項為:bus )

  • v-once指令和動態元件

    動態元件場景,頁面中需要通過按鈕進行元件的切換

    頁面:針對元件新增v-if,進行元件判斷

      <div id="root">
          <child-one v-if="type === 'child-one'"></child-one>
          <child-two v-if="type === 'child-two'"></child-two>
          <button @click="handleBtnClick">change</button>
      </div>
    

    元件配置: 在handleBtnClick方法中,根例項進行三元表示式判斷,通過data中的type進行元件切換

      <script>
          Vue.component('child-one', {
              template: '<div>child-one</div>'
          })
    
          Vue.component('child-two', {
              template: '<div>child-two</div>'
          })
    
          var vm = new Vue({
              el: '#root',
              data: {
                  type: 'child-one'
              },
              methods: {
                  handleBtnClick: function () {
                      this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
                  }
              }
          })
      </script>
    

    改造上述程式碼:

    1. component為動態元件,屬性is繫結元件名稱(對應根例項中data中的type)。

       <!-- component標籤為動態元件 屬性is繫結元件名稱 -->
       <component :is="type"></component>	
      
    2. 採用v-once指令,提高靜態資料內容的渲染效率。

       template: '<div v-once>child-one</div>'
      

    TIPS:本篇內容關於Vue中is特性以及ref和$refs的使用將在後續博文中補充說明。