vue2.x組件間傳值及在vue子組件中操作父組件數據時生命週期的問題

前言

在做項目中遇見一個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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章