Vue組件間傳值

首先 vue 組件化的一個(gè)框架。
既然是組件化。
那么一定存在組件和組件之間傳值的問(wèn)題

在討論組件和組件怎么傳值的問(wèn)題之前,
可以先看看組件與組價(jià)之間有三種關(guān)系。

  1. 父->子
  2. 子->父
  3. 平行組件之間傳值.

1. 父子組件間傳值.

一個(gè)父組件里面包含了一個(gè)子組件,需要把父組件的數(shù)據(jù)傳遞給子組件以便于子組件顯示.

數(shù)據(jù)流動(dòng)方向:父組件數(shù)據(jù) -> 子組件

子組件利用綁定屬性的方式綁定父組件的數(shù)據(jù)屬性,從而獲取父組件的值.

  Vue.component('pview',{
    template:`<div>
    <input type="text" v-model='message'>
    <!-- 這里使用 v-bind 表達(dá)式綁定父容器的數(shù)據(jù)屬性 -->
      <cview :msg="message"></civew>
    </div>`,
    data:function(){
      return {
        message:'message in parentView'
      }
    }
  })

  Vue.component('cview',{
    template:`<p>從父組件獲取到的值:{{msg}}</p>`,
    props:['msg'] // 子組件需要使用 props來(lái)接收
  })
  

html

 <div id='app'>
    <pview></pview>
    <selfview outter-Data='這是普通擴(kuò)展屬性'></selfview>
  </div>

結(jié)果:

父->子傳值.gif

上述demo中,在子組件的頂級(jí)利用 v-bind:表達(dá)式綁定父組件的 data 屬性.并在子組件內(nèi)部使用 props 屬性來(lái)接收這個(gè)msg,即可在子組件內(nèi)部使用{{msg}} or this.msg 了.

補(bǔ)充:

我們可以在子組件標(biāo)簽里使用 v-bind:msg = 父組件數(shù)據(jù)屬性,并子子組件內(nèi)搭配 props:['msg'] 來(lái)獲取到從父組件傳遞過(guò)來(lái)的屬性數(shù)據(jù).

子組件擴(kuò)展屬性

這里的子組件擴(kuò)展屬性和父組件就沒有關(guān)系了,完全是子組件自己的數(shù)據(jù)行為.

數(shù)據(jù)流動(dòng)方向:子組件擴(kuò)展屬性 -> 子組件

Vue.component('selfview', {
    template:`<button @click="on_click"> {{outterData}} -- {{innerData}}</button>`,
    props:['outterData'], // 屬性擴(kuò)展都需要些在這里. *** 注意,擴(kuò)展屬性寫的是 outter-Data ,這里寫的是 outterData .
    data:function() {
      return {
        innerData:'這是組件自己內(nèi)部的數(shù)據(jù)屬性字段'
      }
    }
  })
  
  
  <!-- 注意,這里不是使用的:outter-Data 而是普通的 outter-Data -->
  <selfview outter-Data='這是普通擴(kuò)展屬性'></selfview>
  

html

 <div id='app'>
    <pview></pview>
    <selfview outter-Data='這是普通擴(kuò)展屬性'></selfview>
  </div>

結(jié)果:

子組件自己的普通擴(kuò)展屬性,注意命名方式

總結(jié):

  • 在子組件頂級(jí)標(biāo)簽里可以使用 :msg='父組件屬性'(v-bind:不要忘記冒號(hào)) & props['msg'] 的方式拿到父組件屬性數(shù)據(jù).
  • 也可以完全擴(kuò)展一個(gè)屬性自己的數(shù)據(jù)屬性 msg='自己的擴(kuò)展的屬性值' & props:['msg']

子組件可以通過(guò)擴(kuò)展屬性綁定 :msg='parentMSG' & props:['msg'] 的方式給從父組件那里獲取到值.


子組件往父組件傳值

子組件通過(guò) 屬性 的方式從父組件獲取數(shù)據(jù).

當(dāng)子組件需要向父組件傳遞數(shù)據(jù)(數(shù)據(jù)流向:子組件 -> 父組件) ,一般是通過(guò)事件來(lái)實(shí)現(xiàn).

Vue.component('pview',{
    template:`<div>
      <h3>我是父組件</h3>從子組件傳遞過(guò)來(lái)的值:{{dataFromCview}}
      <cview @send-data-to-pview="showDataFromCView"></cview>
      </div>`,
    data:function() {
      return {
        dataFromCview:''
      }
    },
    methods:{
    // 父組件提供事件響應(yīng)函數(shù),并利用第一個(gè)參數(shù)data獲取子組件傳遞過(guò)來(lái)的數(shù)據(jù)
      showDataFromCView(data) {
        this.dataFromCview = data
      }
    }
  })

  Vue.component('cview',{
    template:`<div>
      <input type='text' v-model='name'/>
      <button  @click='on_click'>傳值</button>
      </div>`,
    data:function(){
      return {
        name:''
      }
    },
    methods:{
      on_click(){
        // 定義了一個(gè)事件,觸發(fā)這個(gè)事件的響應(yīng)函數(shù)是綁定了父組件的showDataFromCview方法,并將子組件的 this.name 屬性以參數(shù)的形式傳遞回去.
        this.$emit('send-data-to-pview',this.name)
      }
    }

  })

html

<div id='app'>
    <pview></pview>
  </div>

結(jié)果:

子->父?jìng)髦?gif

總結(jié):

子組件從父組件傳遞值的時(shí)候,是利用 自定義事件指向父組件的某個(gè)方法,并在子組件內(nèi)部觸發(fā)這個(gè)自定義事件,間接的觸發(fā)定義在父組件身上的方法,在利用參數(shù)的形式將數(shù)據(jù)從子組件傳遞到父組件身上去 .

補(bǔ)充:

當(dāng)然,子組件定義的事件,不光可以綁定和觸發(fā)父組件的方法,也可以直接修改父組件的屬性值.

子組件定義一個(gè) on_change_pview_data_pro 事件,在觸發(fā)這個(gè) on_change_pview_data_pro 事件時(shí),直接修改父組件的 name 屬性.

Vue.component('pview',{
    template:`<div style='border:1px solid black'>
      <h3>我是父組件</h3>
      <p>從子組件傳遞過(guò)來(lái)的值:{{dataFromCview}}</p>
      <p>子組件通過(guò)事件直接修改父組件的name屬性:{{name}}</p>
      <cview @send-data-to-pview="showDataFromCView" @on_change_pview_data_pro="name='通過(guò)事件常量傳值'"></cview>
      </div>`,
    data:function() {
      return {
        dataFromCview:'',
        name: '這是name默認(rèn)值'
      }
    },
    methods:{
      showDataFromCView(data) {
        
        this.dataFromCview = data
      }
    }
  })

  Vue.component('cview',{
    template:`<div style='border:1px solid red;margin:5px;'>
      <p>我是子組件</p>
      <input type='text' v-model='name'/>
      <button  @click='on_click'>傳值</button><br>
      <button @click='on_change_pview_data_pro'>通過(guò)事件直接修改父組件的屬性值</button>
      </div>`,
    data:function(){
      return {
        name:''
      }
    },
    methods:{
      on_click(){
        // 定義了一個(gè)事件,觸發(fā)這個(gè)事件的響應(yīng)函數(shù)是綁定了父組件的showDataFromCview方法,并將子組件的 this.name 屬性以參數(shù)的形式傳遞回去.
        this.$emit('send-data-to-pview',this.name)
      },
      on_change_pview_data_pro() {
       // 子組件直接觸發(fā)事件,沒有傳遞參數(shù),因?yàn)闆]有綁定事件響應(yīng)函數(shù)(父組件的某個(gè)方法)
       // 而是直接修改父組件的某個(gè)數(shù)據(jù)屬性(name)的值為常量(通過(guò)事件常量傳值)
       // @on_change_pview_data_pro="name='通過(guò)事件常量傳值'"
        this.$emit('on_change_pview_data_pro')
      }
    }

  })
  

html

 <div id='app'>
    <pview></pview>
  </div>

結(jié)果

子->父?jìng)髦?直接在事件里修改父組件的屬性值.gif

兩個(gè)平行的組價(jià)之間傳遞消息

首先回顧父子間數(shù)據(jù)如何傳遞的:

  • 數(shù)據(jù)流從父組件 --- >子組件 通過(guò) 屬性

    • 子組件利用屬性 :msg='pmsg' & 'props:['msg']' 拿到父組件的數(shù)據(jù)屬性.
    • 子組件也可以自定義 msg='abc' & props:['msg'] 來(lái)擴(kuò)展自己的自定義屬性.
  • 數(shù)據(jù)流從 子組件 --- > 父組件 通過(guò) 事件

    • 子組件通過(guò)非常正統(tǒng)的 子組件事件 & 父組件事件響應(yīng)方法的方式來(lái)傳遞數(shù)據(jù)
      • 子組件在定義一個(gè)自定義事件,@send-data-to-pview='showDataFromCView' ,給此事件綁定一個(gè)父組件的事件響應(yīng)函數(shù).
      • 子組件在內(nèi)部觸發(fā)這個(gè)自定義事件,并通過(guò)第二個(gè)參數(shù)將數(shù)據(jù)傳遞到父組件事件響應(yīng)方法里.
    // 子組件事件綁定父組件事件響應(yīng)函數(shù)
    <cview @send-data-to-pview="showDataFromCView" ></civew>
    
        // 子組件觸發(fā)這個(gè)事件 & 傳遞參數(shù)
    on_click(){
        this.$emit('send-data-to-pview',this.name)
         },
      
      // 父組件提供事件響應(yīng)方法,并接受參數(shù)
       showDataFromCView(data) {
        this.dataFromCview = data
      }
    
   + 子組件事件直接修改父組件的數(shù)據(jù)屬性值/
   
   ```JavaScript
   // 注意,這里的 name 是父組件的屬性
  <cview @on_change_pview_data_pro="name='通過(guò)事件常量傳值'"></cview>
  
   ```

也就是說(shuō),到目前為止,父子組件間傳遞數(shù)據(jù).

+ 父 --> 子,利用`屬性`
+ 子 --> 父,利用`事件`.


而**平行的兩個(gè)組件之間**,是里用`事件`來(lái)傳遞值的.


**場(chǎng)景**

一個(gè) **talker** 用來(lái)說(shuō)一些話.
一個(gè) **listener** 用來(lái)聽 **talker**說(shuō)的這些話.



```JavaScript

let Event = new Vue()

 Vue.component('talker',{
   template:`<div>
       talker Says: <input type='text' @keyup='isSaying' v-model='content' />
     </div>`,

   data:function(){
     return {
       content:'我還什么都沒說(shuō)'
     }
   },
   methods:{
     isSaying() {
       // Event 通過(guò) $emit,直接發(fā)送一個(gè) event-talker-saying 的事件.
       // 并傳出這個(gè) this.content 數(shù)據(jù).

       Event.$emit('event-talker-saying',this.content)
     }
   }
 })

 Vue.component('listener',{
   template:`<div>
     <span>i heard talker says:</span>
     <span style='font-weight:800;font-size:30px'>{{talkerSay}}</span>
     </div>`,

   data:function(){
     return {
       talkerSay:''
     }
   },
   // 事件監(jiān)聽
   // 當(dāng)組件加載到 DOM 中去時(shí) ,綁定并監(jiān)聽這個(gè)事件
   mounted() {
     Event.$on('event-talker-saying',(content)=>{
       this.talkerSay = content
     })
   },

 })


html

<div id='app'>

    <talker></talker>
    <listener></listener>
  </div>

它倆是平級(jí)的.

結(jié)果

平級(jí)組件間傳值.gif

主要步驟:

  • 使用 new Vue() 構(gòu)造函數(shù),獲取一個(gè)沒有作用域的全局vue事件實(shí)例.Event
  • talker組件在合適的時(shí)機(jī),使用Event觸發(fā)事件event-talker-saying,并傳遞參數(shù).
isSaying() {
        // Event 通過(guò) $emit,直接發(fā)送一個(gè) event-talker-saying 的事件.
        // 并傳出這個(gè) this.content 數(shù)據(jù).

        Event.$emit('event-talker-saying',this.content)
        }

  • listener在合適的時(shí)機(jī)(onmounted()),訂閱事件,并在二個(gè)參數(shù)箭頭函數(shù)里,拿到觸發(fā)事件帶過(guò)來(lái)的數(shù)據(jù).
// 事件監(jiān)聽
    // 當(dāng)組件加載到 DOM 中去時(shí) ,綁定并監(jiān)聽這個(gè)事件
    mounted() {
      Event.$on('event-talker-saying',(content)=>{
        this.talkerSay = content
      })
    },
    
    // 補(bǔ)充一點(diǎn),由于this作用域的問(wèn)題,在這里推薦使用箭頭函數(shù).

最后總結(jié):

  • 數(shù)據(jù)傳遞方向
    • 父 -> 子 利用屬性!!!****屬性!!!****屬性!!!

      • 子組件身上利用屬性

        • 綁定父組件屬性 :msg='pmg'

        • 自己的擴(kuò)展屬性 msg='hellworld'

        • 別忘了子組件內(nèi)部的 props:['msg']

    • 子 -> 父 利用事件!!!****事件!!!****事件!!!

      • 子組件身上自己訂閱自定義事件

        • 事件可以綁定父組件的某個(gè)方法作為事件響應(yīng)函數(shù).

        • 事件也可可以直接以常量的方式修改父組件數(shù)據(jù)屬性的值.

      • 事件定義了,需要觸發(fā).

        • 子組件在合適的時(shí)機(jī)里,去觸發(fā)這個(gè)事件.this.$emit('event-name',param)
    • A -> B 平級(jí)的兩個(gè)組件使用 事件!!!****事件!!!****事件!!!

      • 需要傳遞數(shù)據(jù)的一方,利用一個(gè)全局的事件對(duì)象 let Event = new Vue(),來(lái)觸發(fā)一個(gè)事件,并傳遞事件數(shù)據(jù).
       Event.$emit('event-talker-saying',this.content)
   - 需要接受數(shù)據(jù)的這一方,則在一個(gè)合適的時(shí)機(jī),監(jiān)聽此事件,并根據(jù)第二個(gè)箭頭匿名函數(shù)拿到事件傳遞過(guò)來(lái)的數(shù)據(jù).
        Event.$on('event-talker-saying',(content)=>{
        this.talkerSay = content
      })
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 一. 子組件向父組件傳值 - $emit 發(fā)射事件 1. 子組件$emit發(fā)射事件A 2. 父組件通過(guò)事件名A...
    嗨姑娘_大個(gè)子閱讀 3,948評(píng)論 1 1
  • 前言 您將在本文當(dāng)中了解到,往網(wǎng)頁(yè)中添加數(shù)據(jù),從傳統(tǒng)的dom操作過(guò)渡到數(shù)據(jù)層操作,實(shí)現(xiàn)同一個(gè)目標(biāo),兩種不同的方式....
    itclanCoder閱讀 25,897評(píng)論 1 12
  • 父子組件間傳值 父組件—>子組件:1.父組件使用 v-bind 綁定變量并賦值給變量。2.在子組件里使用 prop...
    廢柴阿W閱讀 189評(píng)論 0 0
  • 組件(Component)是Vue.js最核心的功能,也是整個(gè)架構(gòu)設(shè)計(jì)最精彩的地方,當(dāng)然也是最難掌握的。...
    六個(gè)周閱讀 5,652評(píng)論 0 32
  • vue概述 在官方文檔中,有一句話對(duì)Vue的定位說(shuō)的很明確:Vue.js 的核心是一個(gè)允許采用簡(jiǎn)潔的模板語(yǔ)法來(lái)聲明...
    li4065閱讀 7,270評(píng)論 0 25