vue組件通信

組件通信

  1. 爲什麼要進行組件通信?
    組件可以說是一個具有獨立功能的整體,但是當我們要將這些組件拼接在一起時,這些組件相互之間要建立聯繫
    ,這個聯繫我們就稱之爲通信
  2. 組件通信的方式有以下幾種( 王者級 )
    1. 父子組件通信
      使用props來實現
   <div id="app">
    <Father></Father>
  </div>
  <template id="father">
    <div>
      <h3> 這裏是父組件 </h3>
      <hr>
      <Son :aa = "money" :mask-flag = "maskFlag" :maskFlag = "maskFlag"/>
    </div>
  </template>
  <template id="son">
    <div>
      <h3> 這裏是son組件 </h3>
      <p> 父親給了我  {{ aa }}  錢  </p>
      <p> {{ maskFlag }} </p>
    </div>
  </template>

      Vue.component('Father',{
    template: '#father',
    data () { // 爲什麼要將data定義爲函數?
      return {
        money: 2000,
        maskFlag: 10000000000
      }
    }
  })
  Vue.component('Son',{
    template: '#son',
    props: ['aa','maskFlag']          
  })
  new Vue({
    
  }).$mount('#app')

props
1. 在父組件的模板中將數據用單項數據綁定的形式,綁定在子組件身上

2. 在子組件的配置項中可以使用一個props配置項來接收這個數據,接收時,props的取值可以使一個數組

        Vue.component('Son',{
          template: '#son',
          props: ['money']
        })
  1. 在子組件模板中,接收到的屬性可以像全局變量一樣直接使用

    父親給了我 {{ money }} 錢

    問題: 爲什麼data要定義爲一個函數?
    1. 組件是一個獨立的個體,那麼它應該擁有自己的數據,這個數據應該是一個獨立的數據
    2. 也就是說這個數據應該有獨立作用域,也就是有一個獨立的使用範圍,這個範圍就是這個組件內
    3. js的最大特徵是:函數式編程 , 而函數恰好提供了獨立作用域
    問題: 爲什麼data要有返回值?返回值還是一個對象?
    1. 因爲Vue是通過observer來觀察data選項的,所有必須要有返回值
    2. 因爲Vue要通過es5的Object.defineProperty屬性對對象進行getter和setter設置

  2. 子父組件通信
    自定義事件

 <div id="app">
    <Father></Father>
  </div>
  <template id="father">
    <div>
      <h3> 這裏father組件 </h3>
      <p> 兒子給了我   {{ money }} </p>
      <Son @give = "getHongbao"/>
    </div>
  </template>
  <template id="son">
    <div>
      <button @click = "giveFather"> give </button>
      <h3> 這裏是son組件 </h3>
    </div>
  </template>
    Vue.component('Father',{
    template: '#father',
    data () {
      return {
        money: 0
      }
    },
    methods: {
      getHongbao ( val ) {
        console.log( 1 )
        this.money = val
      }
    }
  })

  Vue.component('Son',{
    template: '#son',
    data () {
      return {
        hongbao: 500
      }
    },
    methods: {
      giveFather () {
        //如何進行父組件給子組件的自定義事件觸發
        this.$emit('give',this.hongbao)
      }
    }
  })
  
  new Vue({
    el: '#app'
  })

註釋
自定義事件
1. 自定義的 通過 $on 定義 $emit觸發
2. 通過綁定在組件身上定義,通過 $emit觸發

子父通信流程
1. 在父組件的模板中,通過事件綁定的形式,綁定一個自定義事件在子組件身上

<Son @aa = “fn”/> //這邊要注意: fn是要在父組件配置項methods中定義

  1. 在子組件的配置項methods中寫一個事件處理程序,在事件處理程序中觸發父組件綁定的自定義事件
          Vue.component('Son',{
            template: '#son',
            data () {
              return {
                hongbao: 500
              }
            },
            methods: {
              giveFather () {
                //如何進行父組件給子組件的自定義事件觸發
                this.$emit('give',this.hongbao)
              }
            }
          })
  1. 將子組件定義的事件處理程序 giveFather,綁定在子組件的按鈕身上
           <template id="son">
              <div>
                <button @click = "giveFather"> give </button>
                <h3> 這裏是son組件 </h3>
              </div>
            </template>
  1. 非父子組件通信
    ref鏈: 可以實現非父子組件的通信,但是如果層級太多,就比較繁瑣了 $attrs
<div id="app">
    <Father></Father>
  </div>
  <template id="father">
    <!-- 組件中根元素必須唯一 -->
    <div>
      <h3> 這裏是father  </h3>
      <button @click = "look"> 點擊查看father的this </button>
      <p> father的 n: {{ n }} </p>
      <hr>
      <Son ref = "son"></Son>
      <Girl ref = "girl" :n = "n"></Girl>
    </div>
  </template>

  <template id="son">
    <div>
      <h3> 這裏是 son 1 </h3>
    </div>
  </template>

  <template id="girl">
      <div>
        <h3> 這裏是girl </h3>
        <button @click = "out"> 輸出girl的this </button>
      </div>
  </template>
   Vue.component('Father',{
    template: '#father',
    data () {
      return {
        n: 0
      }
    },
    methods: {
      look () {
        this.n = this.$refs.son.money 
      }
    }
  })

  Vue.component('Son',{
    template: '#son',
    data () {
      return {
        money: 1000
      }
    }
  })

  Vue.component('Girl',{
    template: '#girl',
    data () {
      return {
        num: 0
      }
    },
    methods: {
      out () {
        console.log( this )
        console.log( this.$attrs )
      }
    }
  })

  new Vue({
    el: '#app'
  })

bus事件總線

<div id="app">
    <Bro></Bro>
    <Sma></Sma>
  </div>
  <template id="big">
    <div>
      <h3> 這裏是哥哥組件  </h3>
      <button @click = "hick"> 揍 </button>
    </div>
  </template>

  <template id="small">
    <div>
      <h3> 這裏是弟弟組件 </h3>
      <p v-show = "flag"> 嗚嗚嗚嗚嗚嗚嗚嗚嗚uwuwuwuwu </p>
    </div>
  </template>
 var bus = new Vue() // bus原型上是不是有  $on   $emit 

  Vue.component('Bro',{
    template: '#big',
    methods: {
      hick () {
        bus.$emit('aa')
      }
    }
  })


  Vue.component('Sma',{
    template: '#small',
    data () {
      return {
        flag: false
      }
    },
    mounted () { //當前組件掛載結束,也就是我們可以在頁面當中看到真實dom
      // mounted這個鉤子函數的觸發條件是組件創建時會自動觸發
      // 事件的聲明
      var _this = this 
      bus.$on( 'aa',function () {
        _this.flag = true
        console.log( this )//這裏是this指的是bus, 但是我們需要的this應該是Sma這個組件
      })
    }
  })

  new Vue({
    el: '#app'
  })

註釋
bus事件總線,我們是通過 $on來定義事件, 通過 $emit來觸發事件
案例: 哥哥揍弟弟,弟弟哭

流程:
1. 在其中一個組件的 掛載鉤子函數 上 做事件的聲明

          Vue.component('Sma',{
            template: '#small',
            data () {
              return {
                flag: false
              }
            },
            mounted () { //當前組件掛載結束,也就是我們可以在頁面當中看到真實dom
              // mounted這個鉤子函數的觸發條件是組件創建時會自動觸發
              // 事件的聲明
              var _this = this 
              bus.$on( 'aa',function () {
                _this.flag = true
                console.log( this )//這裏是this指的是bus, 但是我們需要的this應該是Sma這個組件
              })
            }
          })
  1. 在另一個組件中 通過 bus.$emit(‘aa’)來觸發這個自定義事件

app實例的手動掛載

  new Vue({
    
  }).$mount('#app')

自定義事件

  1. 自定義的 通過 $on 定義 $emit觸發

       var vm = new Vue({
       el: '#app'
       })
    
       // 自定義事件的定義( 發佈 )
    
       // vm.$on(自定義事件的名稱,自定義事件的事件處理程序)
    
       vm.$on( 'aa', function () {
       console.log( 'aa' )
       })
    
       //自定義事件的觸發 ( 訂閱 )
    
       // vm.$emit( 自定義事件的名稱,自定義事件處理程序需要的參數1,參數2,參數3)
    
       vm.$emit( 'aa' )
    
  2. 通過綁定在組件身上定義,通過 $emit觸發
    <Son @aa = “fn”/>

    使用: 子父通信

組件的根元素必須有且僅有一個

動態組件

  1. 什麼是動態組件?
    可以改變的組件
  2. 使用
    通過 Vue 提供了一個 component + is 屬性
  3. 動態組件指的就是 component這個組件
  4. 案例
    <div id="app">
       <button @click = "change"> 切換 </button>
       <keep-alive include="">
          <component :is = "type"></component>
       </keep-alive>
    </div>
    
      Vue.component('Aa',{
          template: '<div> Aa </div>'
       })
    
       Vue.component('Bb',{
          template: '<div> Bb </div>'
       })
    
       new Vue({
          data: {
             type: 'Aa'
          },
          methods: {
             change () {
             this.type = (this.type === 'Aa'?'Bb':'Aa')
             }
          }
       }).$mount('#app')
    
  5. Vue提供了一個叫做 keep-alive 的組件可以將我們的組件進行瀏覽器緩存,這樣當我們切換組件時,就可以大大提高使用效率
  6. keep-alive也可以以屬性的形式呈現,但是我們如果搭配component的話,建議使用組件的形式
<div id="app">
    <button @click = "change"> 切換 </button>
    <!-- <keep-alive include="">
      <component :is = "type"></component>
    </keep-alive> -->
    <component :is = "type"></component>
     </div>
 Vue.component('Aa',{
    template: '<div> Aa </div>'
  })

  Vue.component('Bb',{
    template: '<div> Bb </div>'
  })

  new Vue({
    data: {
      type: 'Aa'
    },
    methods: {
      change () {
        this.type = (this.type === 'Aa'?'Bb':'Aa')
      }
    }
  }).$mount('#app')

slot 插槽

  1. 作用/概念: 預先將將來要使用的內容進行保留
<div id="app">
    <Hello>
      <div>
        這裏是地球
      </div>
    </Hello>
  </div>
  <template id="hello">
    <div>
      <slot></slot>
      <h3>這裏是hello</h3>
    </div>
  </template>
    Vue.component('Hello',{
    template: '#hello'
  })

  new Vue({
    el: '#app'
  })

運行結果:‘這裏是地球’會插在這裏是hello的前面
2. 具名插槽: 給slot起個名字

<div id="app">
    <Hello>
      <header slot = 'header'> 這裏是頭部 </header>
      <footer slot = 'footer'> 這裏是底部 </footer>
    </Hello>
  </div>
  <template id="hello">
    <div>
      <slot name = "header"></slot>
      <h3>這裏是hello</h3>
      <slot name = "footer"></slot>
    </div>
  </template>
  Vue.component('Hello',{
    template: '#hello'
  })

  new Vue({
    el: '#app'
  })

運行結果:
在這裏插入圖片描述

  • 注意: 以上兩種形式在 vue2.6以上被廢棄
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章