vue通訊的N種方式

燦兒哈擦蘇發表於2019-07-10

元件通訊可以分為父子元件通訊、非父子元件通訊,可以是資料的傳遞,也可以是方法的傳遞,先介紹資料的相互傳遞,再介紹方法的相互傳遞。

父元件到子元件傳遞資料:

一、通過props,父元件可以傳遞動態和靜態資料。

//父元件
<template>
  <div id="app">
  	//第一種靜態資料 <HelloWorld msg="我是父元件的資料"/>
    //第二種動態繫結 <HelloWorld :msg="message"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  data(){
    return{
      message: '我來自父元件'
    }
  },
  components: {
    HelloWorld
  }
}
</script>
複製程式碼

//子元件
<template>
  <div class="hello">
    來自父元件的值:{{msg}}
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: ['msg']
  //或者 props: { msg: String//指定傳入的型別 }
  //或者 props: { msg: String,default: '預設值' //指定預設值 }
}
</script>複製程式碼

二、provide / inject

provide 和 inject 主要為高階外掛/元件庫提供用例。並不推薦直接用於應用程式程式碼中。並且這對選項需要一起使用,以允許一個祖先元件向其所有子孫後代注入一個依賴,不論元件層次有多深,並在起上下游關係成立的時間裡始終生效。

//父元件
<template>
   <div>
     <child-dom>
     </child-dom>
   </div>
</template>
<script>
   import childDom from "./components/ChildDom.vue";
   export default {
     data() {
       return{

       }
     },
     provide: {
      house: '房子',
      car: '車子',
      money: '¥10000'
    },
     methods:{
      
     },
     components:{childDom},
   }
</script>複製程式碼

//子元件
<template>
   <div>
    
   </div>
</template>
<script>

   export default {
     data() {
       return{

       }
     },
     inject: {
	    house: {
	      default: '沒房'
	    },
	    car: {
	      default: '沒車'
	    },
	    money: {
	      default: '¥4500'
	    }
	  },
	  created () {
	    console.log(this.house, this.car, this.money)
	  },
	  methods:{
      
      }
   }
</script>
複製程式碼

子元件傳值給父元件

一、通過props的回撥

//父元件
<template>
  <div id="app">
    <HelloWorld :msg="message"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  data(){
    return{
      
    }
  },
  methods: {
    message: (data)=>{
      console.log('我是父元件的方法,在子元件中被觸發了')
      console.log('來自子元件的值是:'+data)
    }
  },
  components: {
    HelloWorld
  }
}
</script>複製程式碼

//子元件
<template>
  <div class="hello" @click="msg('來自子元件的值~~')">
    來自父元件的方法,點我執行
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: ['msg']
}
</script>複製程式碼

二、通過$emit

//父元件
<template>
  <div id="app">
    <HelloWorld @getData="message"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  data(){
    return{
      
    }
  },
  methods: {
    message: (data)=>{
      console.log('來自子元件的值是:'+data)
    }
  },
  components: {
    HelloWorld
  }
}
</script>複製程式碼

//子元件
<template>
  <div class="hello" @click="goFun">
    點選傳值給父元件
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data(){
    return{
      s: 1111
    }
  },
  methods: {
    goFun(){
      this.$emit('getData',this.s)
    }
  }
}
</script>複製程式碼

三、.sync修飾實現雙向繫結

//父元件
<template>
  <div id="app">
    <HelloWorld :show.sync='valueChild'/>
    父元件值:{{valueChild}}
    <button @click="changeValue">點選</button>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  data(){
    return{
      valueChild:true
    }
  },
  methods: {
    changeValue(){
      console.log('父元件的值被修改:'+this.valueChild)
      this.valueChild =!this.valueChild
    }
  },
  components: {
    HelloWorld
  }
}
</script>複製程式碼

//子元件
<template>
  <div>
    <div>
      <p>子元件值:{{show}}</p>
      <button @click.stop="closeDiv">修改</button>
    </div>
    </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  methods: {
    closeDiv() {
      this.$emit('update:show', !this.show); //觸發 input 事件,並傳入新值
    }
  },
  props:['show']
}
</script>複製程式碼

關係型元件跨級傳遞(根元件、兒子元件、孫子元件)

一、使用 $attrs 和 $listeners

通過 $attrs 將值連續往下傳遞(和props傳遞類似),傳遞過程中可以只選擇當前需要的值,元件中可以通過 inheritAttrs:false 保持當前元件的屬性純淨度。通過 $listeners 可以在(…子元件)中 this. $emit(“upRocket”,11111)來觸發父元件中的事件,從而達到傳值給父元件的目的。

//父元件
<template>
   <div>
     <child-dom
      :foo="foo"
      :coo="coo"
      @upRocket="reciveRocket"
     >
     </child-dom>
   </div>
</template>
<script>
   import childDom from "./components/ChildDom.vue";
   export default {
     data() {
        return {
          foo:"Hello, world",
          coo:"Hello,rui"
        }
     },
     methods:{
       reciveRocket(data){
          console.log("我是根元件,這是接受的孫子元件的資料"+data)
       }
     },
     components:{childDom},
   }
</script>複製程式碼

//子元件
<template>
   <div>
      <p>foo:{{foo}}</p>
      <childDomChild v-bind="$attrs" v-on="$listeners"></childDomChild>
   </div>
</template>
<script>
import childDomChild from './childDomChild';
export default {
 name:'child-dom',
 props:["foo"],
 inheritAttrs:false,
 components:{childDomChild}
}
</script>複製程式碼

//孫子元件
<template>
   <div>
      <p>coo:{{coo}}</p> 
      <button @click="startUpRocket">傳送資料到根元件</button>   </div>
</template>
<script>

export default {
 name:'child-dom',
 props:["coo"],
 methods: {
     startUpRocket() {
      this.$emit("upRocket");
     }
  }
}
</script>複製程式碼

二、$parent $children

其實通過 $ r e f 可以獲取到子元件中的一些掛載屬性和值, 父元件如果要獲取子元件的方法可以通過this.$refs.mychild.funName("…");這種方式,給子元件指定ref名稱。同理,通過 $parent $children可直接運算元據和方法。

  • this. $parent查詢當前元件的父元件。
  • this.$children查詢當前元件的直接子元件,可以獲取到全部直接子元件, 需要注意$children 並不保證順序,也不是響應式的。可以通過this.$root.$children[0].$children[0].$children[0].msg連續查詢
  • this.$root查詢根元件,並可以配合$children遍歷全部元件

//父元件
<template>
   <div>
    父元件的值:{{msg}}
     <child-dom>
     </child-dom>
     <button @click="change">父元件點選修改</button>
   </div>
</template>
<script>
   import childDom from "./components/ChildDom.vue";
   export default {
     data() {
       return{
        msg: 0
       }
     },
     methods:{
      change(){
        this.msg = this.$children[0].childMsg
        this.$children[0].childMsg = '子元件的值被父元件修改了'
      }
     },
     mounted(){
     
     },
     components:{childDom},
   }
</script>複製程式碼

//子元件
<template>
   <div>
      子元件的值:{{childMsg}}
      <button @click="decrease()">子元件點選修改</button>
   </div>
</template>
<script>
export default {
  name:'child-dom',
  data() {
    return {
      childMsg : 111
    };
  },
  methods: {
    decrease() {
      this.childMsg = this.$parent.msg
      this.$parent.msg = "子元件修改了父元件的值"
    }
  }
}
</script>複製程式碼

非關係元件傳值

一、EventBus

適用於小型專案,可以達到任意元件相互通訊的效果

//元件a
<template>
   <div>
    {{fontCount}}
     <child-dom>
     </child-dom>
   </div>
</template>
<script>
   //import Vue from 'vue'   //export const EventBus = new Vue()
   import { EventBus } from "./assets/bus.js";
   import childDom from "./components/ChildDom.vue";
   export default {
     data() {
       return{
        fontCount: 0
       }
     },
     methods:{
     },
     mounted(){
      EventBus.$on("decreased", ({num}) => {
        this.fontCount -= num
      });
     },
     components:{childDom},
   }
</script>複製程式碼

//元件b
<template>
   <div>
      <button @click="decrease()">-</button>
   </div>
</template>
<script>
import { EventBus } from "../assets/bus.js";
export default {
  name:'child-dom',
  data() {
    return {
      num: 1,
      deg:180
    };
  },
  methods: {
    decrease() {
      EventBus.$emit("decreased", {
        num:this.num
      });
    }
  }
}
</script>複製程式碼

二、vuex

請移步官方文件查閱具體內容


相關文章