在使用vue進行組件開發的時候,遇到一個問題,父組件傳遞到子組件裏面的值,若是在子組件裏面進行改變 傳遞過來的"值",會報錯:vue
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "result" (found in component )
緣由:props 傳遞數據流是單向的,父組件傳遞到子組件是單向的。this
例如:父組件傳遞值spa
<tabs :tabs="tabs" :activeIndex="activeIndex" ></tabs>
子組件接受值:code
<template> <el-tabs type="card" v-model="activeIndex"> <el-tab-pane v-for="(item,index) in tabs" :label="item" :closable="index==0?false:true" :name="index.toString()"> </el-tab-pane> </el-tabs> </template> <script> export default{ data(){ return { tabs:[] } }, props:['activeIndex'] } </script>
咱們在父組件改變 activeIndex 的值,子組件會發生變化,可是咱們注意到在子組件一樣也會改變值,就會產生:component
Avoid mutating a prop directly since the value will be overwritten ....的報錯blog
緣由在於:父子組件的傳遞機制ip
解決辦法:在子組件使用該值的時候,能夠經過定義變量(currentIndex)來進行傳遞,這個值發生改變的時候,不會形成activeIndex的改變:開發
<script> export default{ data(){ return { tabs:[], currentIndex:this.activeIndex } }, props:['activeIndex'] } </script>
基本上這樣處理,就可以解決報錯問題了。it
可是咱們想要子組件的 currentIndex 發生改變的時候,父組件的 activeIndex 也要發生改變,要怎麼作呢?io
咱們知道:activeIndex 是經過父組件傳遞過來的,用 props 進行接受,可是數據流動是單向,也就是在子組件的 currentIndex 發生改變,父組件的 activeIndex不會變。
這要怎麼解決?
使用 $emit 的目的在於:實現子組件向父組件的通訊;
具體實現:定義 $emit的方法[ indexChange ] 並進行傳遞:
<tabs :tabs="tabs" :activeIndex="activeIndex" @indexChange="indexChange"></tabs> <el-button @click="change">改變</el-button> <script> export default{ data(){ return { tabs:[], activeIndex:1; } }, methods:{ change(){ this.activeIndex = 2; }, indexChange(index){ this.activeIndex = index; }, } } </script>
子組件監聽:currentIndex 的變化並向父組件進行通訊:
<template> <el-tabs type="card" v-model="activeIndex"> <el-tab-pane v-for="(item,index) in tabs" :label="item" :closable="index==0?false:true" :name="index.toString()"> </el-tab-pane> </el-tabs> </template> <script> export default{ data(){ return { tabs:[], currentIndex:this.activeIndex } }, props:['activeIndex'], watch:{ currentIndex:function(index){ this.$emit('indexChange',index); } } } </script>