1. 程式人生 > 實用技巧 >vue元件間傳值總結

vue元件間傳值總結

vue 元件間傳值總結:

  • 父元件向子元件傳值
  • 子元件向父元件傳值
  • 祖孫元件間傳值
  • 兄弟元件間傳值

父元件向子元件傳值

基本思路:

在父元件中使用子元件,以屬性繫結的方式繫結資料到子元件上,子元件通過 props 屬性接收,即可實現父元件向子元件傳值。參照下面的例子。

father.vue

<template>
  <div class="father">
    <div>我是父元件</div>
    <child :words="msg"></child>
  </div>
</template>
<script>
import child from '@/components/child.vue'
export default {
  name: 'Home',
  components: {
    child
  },
  data () {
    return {
      msg: "我是父元件傳遞的值"
    }
  }
}
</script>

child.vue

<template>
  <div class="child">
    <div>我是子元件</div>
    <span class="words">{{words}}</span>
  </div>
</template>
<script>
export default {
  props: ['words']
}
</script>
<style scoped>
  .child {
    background: pink;
  }
  .words {
    color: red;
  }
</style>

顯示結果如下:當前頁面為父元件渲染出來的頁面效果,粉紅背景區域為子元件渲染部分,紅色的字是父元件向子元件傳遞的值。

子元件向父元件傳值

  • 子元件使用 $emit() 向父元件傳值,$emit('自定義事件名', 引數)
  • 父元件使用 v-on 監聽子元件傳遞的自定義事件

home.vue

<template>
  <div class="father">
    <div>我是父元件</div>
    <child @receiveMeg="handleMeg($event)"></child>
    <div>{{message}}</div>
  </div>
</template>
<script>
import child from '@/components/child.vue'
export default {
  components: {
    child
  },
  data () {
    return {
      message: ''
    }
  },
  methods: {
    handleMeg (msg) {
      console.log(msg)
      this.message = msg
    }
  }

}
</script>

child.vue

<template>
  <div class="child">
    <div>我是子元件</div>
    <button @click="transMsg">點擊向父元件傳值</button>
  </div>
</template>
<script>
export default {
  data () {
    return {
      childMeg: '我是子元件的資料'
    }
  },
  methods: {
    transMsg () {
      this.$emit('receiveMeg', this.childMeg)
    }
  }
}
</script>
<style scoped>
  .child {
    background: pink;
  }
</style>

顯示結果如下:當點選按鈕時,子元件通過 this.$emit('receiveMeg', this.childMeg) 將子元件中的資料傳遞出去,在父元件中通過監聽子元件傳遞的自定義事件獲取到子元件中的資料。

祖孫元件傳值

祖孫元件傳值實際上是在父子元件傳值的基礎上再次傳遞了一層,father元件實際上充當了過渡者的角色,本質上還是父子元件傳值的套路。

祖向孫傳值

grandfather.vue

<template>
  <div class="father">
    <div>我是GrandFather元件</div>
    <child :msg='message'></child>
  </div>
</template>
<script>
import child from '@/components/child.vue'
export default {
  components: {
    child
  },
  data () {
    return {
      message: '我是GrandFather元件的資料'
    }
  }
}
</script>

father.vue

<template>
  <div class="child">
    <div>我是father元件</div>
    <grandson :parentmsg="msg"></grandson>
  </div>
</template>
<script>
import grandson from '@/components/grandson.vue'
export default {
  props: ['msg'],
  components: {
    grandson
  }
}
</script>
<style scoped>
  .child {
    background: pink;
  }
</style>

grandSon.vue

<template>
  <div class="grandson">
    <div>我是grandson元件</div>
    <div>{{parentmsg}}</div>
  </div>
</template>
<script>
export default {
  props:['parentmsg']  
}
</script>
<style scoped>
.grandson {
  background: #ccc;
}
</style>

孫向組傳值

grandFather.vue

<template>
  <div class="father">
    <div>我是GrandFather元件</div>
    <child @receiveGrandSon="handleMsg"></child>
    <div>{{msg}}</div>
  </div>
</template>
<script>
import child from '@/components/child.vue'
export default {
  components: {
    child
  },
  data () {
    return {
      msg: ""
    }
  },
  methods: {
    handleMsg(msg) {
      this.msg = msg
    }
  }
}
</script>

father.vue

<template>
  <div class="child">
    <div>我是father元件</div>
    <grandson @listenGrandSon="sendFather"></grandson>
  </div>
</template>
<script>
import grandson from '@/components/grandson.vue'
export default {
  components: {
    grandson
  },
  methods: {
    sendFather (msg) {
      this.$emit('receiveGrandSon', msg)
    } 
  }
}
</script>
<style scoped>
  .child {
    background: pink;
  }
</style>

grandSon.vue

<template>
  <div class="grandson">
    <div>我是grandson元件</div>
    <button @click="sendMsg">孫向祖傳值</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg: '我是來自孫元件的值'
    }
  },
  methods: {
    sendMsg() {
      this.$emit('listenGrandSon', this.msg)
    }
  }
}
</script>
<style scoped>
.grandson {
  background: #ccc;
}
</style>

效果如下:

另外一種祖孫元件傳值

中間元件(父元件)使用 v-bind="$attrs"v-on="$listeners" 簡化傳值操作。$attrs 是祖元件向孫元件傳遞的值,$listeners 是孫元件向祖元件傳遞的值。

祖傳孫

父元件新增 v-bind="$attrs" : 祖孫元件的程式碼如上面通過 props 傳值方式,grandSon元件接收時直接接收grandFather繫結的屬性即可。修改父元件的程式碼如下:

<template>
  <div class="child">
    <div>我是father元件</div>
    <grandson v-bind="$attrs"></grandson>
  </div>
</template>
<script>
import grandson from '@/components/grandson.vue'
export default {
  components: {
    grandson
  }
}
</script>

孫傳祖

父元件新增 v-on="$listeners" :同祖向孫傳值類似,父元件新增 v-on="$listeners" ,祖元件直接監聽孫元件傳遞過來的自定義事件即可。

孫元件向祖元件觸發自定義事件時有兩種方式:

  • this.$listeners.eventName(param)
  • this.$emit('eventName', param)
<template>
  <div class="child">
    <div>我是father元件</div>
    <grandson v-on="$listeners"></grandson>
  </div>
</template>
<script>
import grandson from '@/components/grandson.vue'
export default {
  components: {
    grandson
  }
}
</script>

兄弟元件間傳值

  • 兄弟元件間傳值需要藉助事件中心,通過事件中心傳遞資料
  • 事件中心的定義方式:const bus = new Vue();
  • 傳遞資料方:通過一個事件觸發 bus.$emit('監聽的事件', 傳遞的資料)
  • 接收資料方:通過 mounted (){} 鉤子函式中觸發 bus.$on('監聽的事件', param => {}) 方法獲取,回撥函式中的 param 就是兄弟元件傳遞的資料。
  • 銷燬事件:通過 bus.$off('監聽的事件') 銷燬之後,無法進行資料的傳遞。

1.新建一個 eventbus.js 檔案,定義事件中心

import Vue from 'vue'

export default new Vue

2.新建第一個兄弟元件(傳送方),引入事件中心bus,通過 bus.$emit('監聽的事件', 傳遞的資料)向外傳遞一個監聽事件並傳遞資料。

<template>
  <div id="first">
    <h2>第一個兄弟元件</h2>
    <button @click="sendMsg">向兄弟元件傳值</button>
  </div>
</template>
<script>
import bus from '../assets/event-bus'
export default {
  data () {
    return {
      msg: '我是first元件中的資料'
    }
  },
  methods: {
    sendMsg () {
      bus.$emit('receiveMsg', this.msg)
    }
  }
}
</script>

3.新建第二個兄弟元件(接收方),引入事件中心bus,在 mounted 鉤子函式中,通過 bus.$on() 監聽 receiveMsg 事件,回撥函式的引數用來接收傳遞過來的資料。

<template>
  <div id="second">
    <h2>第二個兄弟元件</h2>
    <button @click="sendMessage">向兄弟元件傳值</button>
    <div>{{msg}}</div>
  </div>
</template>

<script>
import bus from '../assets/event-bus'
export default {
  data () {
    return {
      msg: ''
    }
  },
  mounted () {
    bus.$on("receiveMsg", msg => {
      this.msg = msg
    })
  }
}
</script>

4.父元件引入上面的倆元件,通過 bus.$off() 可以銷燬事件,銷燬之後就不可以傳值了。

<template>
  <div class="father">
    <button @click="destroyBus">銷燬事件</button>
    <first></first>
    <second></second>
  </div>
</template>
<script>
import bus from '../assets/event-bus'
import first from '@/components/first.vue'
import second from '@/components/second.vue'
export default {
  components: {
    first,
    second
  },
  methods: {
    destroyBus () {
      bus.$off('receiveMsg')
    }
  }
}
</script>

參考文章:https://juejin.im/post/6844903686926254087
https://blog.csdn.net/qq_40738077/article/details/106765455