前言
在做項目中遇見一個bug, vue在子組件內部操作父組件數據時,在生命週期mounted和created中給頁面渲染父組件的值頁面渲染是正常的,但是控制檯會報錯找不到值! 此文記錄下vue組件之間如何傳值取值,和bug的解決方法。
正文
父組件給子組件傳值—props 實現父組件向子組件傳值。
父組件內:msg是綁定的自定義屬性,類似我們原生html 給標籤自定義屬性一樣
<child-pack :msg ="myMsg" @listenTochildEvent="changeFromChild"></child-pack>
<script >
import childpack from './childPack.vue' //引用子組件
export default{
name: 'FatherPack',
components: { childpack },
data(){
return(){
myMsg:‘我是父組件參數’,
fartherMsg:{
testMsg:{
code:01,
name:'test'
}
}
}
},
mothods:{
changeFromChild(item,){
//一些操作
}
}
}
</script>
子組件傳值到父組件 – this.$emit()
在子組件中:
export default{
methods: {
changeFather(){
this.$emit("listenTochildEvent","我是子組件的參數");
},
//可以傳遞參數,參數可以是值、對象、數組等類型。
// changeFather(pms){
// this.$emit("listenTochildEvent",pms);
// },
} }
父組件如何取值 - - v:on 綁定this.$emit傳過來的事件
<child-pack :msg ="myMsg" @listenTochildEvent="changeFromChild"></child-pack>
export default{
methods: {
changeFromChild(evnet){
console.log(evnet)//"我是子組件的參數"
},
} }
子組件如何取值 – props
<div>
<span>{{msg}}</span>
</div>
export default {
name: 'ChildPack',
props:["msg"]
//也可以指定默認類型和默認值
// props: {
// msg: {
// type: Number,
// default: 0
// }
// },
data(){
},
created() {
console.log('child_msg',this.msg)
},
mothods:{
},
}
這種簡單展示msg是不會報錯的,實際項目中會遇到傳遞過來的值是數組對象,二維數組,需要取內部的值展示或操作,這時就是前言中所遇見的bug。
子組件如何正確操作父組件傳遞過來的數據。
首先說一下:
在沒有任何任何顯示與隱藏限制條件的情況下,運行的順序依次是:
父組件created→父組件beforeMounted→子組件created→子組件beforeMounted→子組件mounted→父組件mounted;
- vue項目裏面在mounted以前的週期內的變化是不會觸發updated的,只有在mounted纔可以;
- 關於vue生命週期的詳細內容可以參考:https://www.jb51.net/article/145474.htm
- 這裏主要說一下,子組件如何正確操作父組件傳遞過來的複雜數據的內部元素
- 首先 在子組件data中掛載一個屬性,用來接收父組件傳過來的值,原因:避免之後涉及到操作數據時報錯
- 在watch監聽中賦值並進行操作,爲了發現對象內部值的變化,可以在選項參數中指定 deep: true 。注意監聽數組的變動不需要這麼做。
- 這樣就不會拋父組件傳過來的對象或屬性爲空的錯誤了~~
<div>
<span>{{data.name}}</span>
</div>
export default {
name: 'ChildPack',
//也可以指定默認類型和默認值
props: {
fartherMsg: {
type: Object,
}
},
data(){
data:{}
},
created() {
console.log(this.fartherMsg.testMsg) // error
},
mounted(){
console.log(this.fartherMsg) // {}
},
updated(){
console.log(this.fartherMsg.testMsg) //{code:01,name:'test'}
},
watch:{
fartherMsg:{
handler(newVal,oldVal){
this.data = this.fartherMsg.testMsg
},
deesp:true
}
}
兄弟之間傳值 – 借用中央事件總線 bus
既然都寫到這了那就就把這個傳值也記錄一下
方法一:在外部新建一個js文件,取名Bus.js, 在這個文件裏實例化一下vue;然後在組件A和組件B中分別引入這個bus.js文件,將事件監聽和事件觸發都掛到bus.js這個實例上,這樣就可以實現全局的監聽與觸發了。
//Bus.js內容
import Vue from 'vue'
export default new Vue()
// 組件一 ,監聽事件send
<template>
<div>
<span>{{name}}</span>
</div>
</template>
<script>
import Bus from './bus.js'
export default {
data () {
return {
name: ''
}
},
created() {
let _this = this
// 用$on監聽事件並接受數據
Bus.$on('send', (data) => {
_this.name = data
console.log(data)
})
},
methods: {}
}
</script>
// 組件二, 觸發事件send
<template>
<div>
<input type="button" value="點擊觸發" @click="onClick">
</div>
</template>
<script>
import Bus from './bus.js'
export default {
data () {
return {
elValue: '我是B組件數據'
}
},
methods: {
// 發送數據
onClick() {
Bus.$emit('send', this.elValue)
}
}
}
</script>
方法二 :在main.js,在vue的原型上添加一個bus對象;
//在mian.js中
Vue.prototype.bus = new Vue() //這樣我們就實現了全局的事件總線對象
//組件A中,監聽事件
this.bus.$on('updata', function(data) {
console.log(data) //data就是觸發updata事件帶過來的數據
})
//組件B中,觸發事件
this.bus.$emit('updata', data) //data就是觸發updata事件要帶走的數據
方法三:使用vuex 詳細介紹看我之前的文章- vue-cli項目全局使用和配置vuex
https://blog.csdn.net/weixin_43216105/article/details/88065159
如果本文對你有幫助的話,請給我點贊打call哦~o( ̄▽ ̄)do
有其他問題留言 over~
關於兄弟傳值 借鑑 :https://blog.csdn.net/wxl1555/article/details/84646832
關於生命週期 借鑑 :https://www.jb51.net/article/145474.htm