在 vue 项目实际开发中我们经常会使用 props 和 emit 来进行子父组件的传值通信, 父组件向子组件传递数据是通过 prop 传递的,
子组件传递数据给父组件是通过 $emit 触发事件来做到的. 例如:
- Vue.component('child',{
- data(){
- return {
- mymessage:this.message
- }
- },
- template:`
- <div>
- <input type="text" v-model="mymessage" @input="passData(mymessage)"> </div>
- `,
- props:['message'],// 得到父组件传递过来的数据
- methods:{
- passData(val){
- // 触发父组件中的事件
- this.$emit('getChildData',val)
- }
- }
- })
- Vue.component('parent',{
- template:`
- <div>
- <p>this is parent compoent!</p>
- <child :message="message" v-on:getChildData="getChildData"></child>
- </div>
- `,
- data(){
- return {
- message:'hello'
- }
- },
- methods:{
- // 执行子组件触发的事件
- getChildData(val){
- console.log(val)
- }
- }
- })
- var App=new Vue({
- el:'#app',
- template:`
- <div>
- <parent></parent>
- </div>
- `
- })
既然是新姿势当然要介绍一下骚操作
1.$attrs 和 $listeners
适用场景: 父组件 A 下面有子组件 B, 组件 B 下面有组件 C, 这时候如果 A 组件想传值给 C 组件就可以用 $attrs 和 $listeners
- Vue.component('C',{
- template:`
- <div>
- <input type="text" v-model="$attrs.messagec" @input="passCData($attrs.messagec)"> </div>
- `,
- methods:{
- passCData(val){
- // 触发父组件 A 中的事件
- this.$emit('getCData',val)
- }
- }
- })
- Vue.component('B',{
- data(){
- return {
- mymessage:this.message
- }
- },
- template:`
- <div>
- <input type="text" v-model="mymessage" @input="passData(mymessage)">
- <!-- C 组件中能直接触发 getCData 的原因在于 B 组件调用 C 组件时 使用 v-on 绑定了 $listeners 属性 -->
- <!-- 通过 v-bind 绑定 $attrs 属性, C 组件可以直接获取到 A 组件中传递下来的 props(除了 B 组件中 props 声明的) -->
- <C v-bind="$attrs" v-on="$listeners"></C>
- </div>
- `,
- props:['message'],// 得到父组件传递过来的数据
- methods:{
- passData(val){
- // 触发父组件中的事件
- this.$emit('getChildData',val)
- }
- }
- })
- Vue.component('A',{
- template:`
- <div>
- <p>this is parent compoent!</p>
- <B :messagec="messagec" :message="message" v-on:getCData="getCData" v-on:getChildData="getChildData(message)"></B>
- </div>
- `,
- data(){
- return {
- message:'hello',
- messagec:'hello c' // 传递给 c 组件的数据
- }
- },
- methods:{
- getChildData(val){
- console.log('这是来自 B 组件的数据')
- },
- // 执行 C 子组件触发的事件
- getCData(val){
- console.log("这是来自 C 组件的数据:"+val)
- }
- }
- })
- var App=new Vue({
- el:'#app',
- template:`
- <div>
- <A></A>
- </div>
- `
- })
2.provide 和 inject
适用场景: 父组件中通过 provider 来提供变量, 然后在子组件中通过 inject 来注入变量. 不论子组件有多深, 只要调用了 inject 那么就可以注入 provider 中的数据. 而不是局限于只能从当前父组件的 prop 属性来获取数据, 只要在父组件的生命周期内, 子组件都可以调用.
- Vue.component('child',{
- inject:['for'],// 得到父组件传递过来的数据
- data(){
- return {
- mymessage:this.for
- }
- },
- template:`
- <div>
- <input type="tet" v-model="mymessage">
- </div>
- })
- Vue.component('parent',{
- template:`
- <div>
- <p>this is parent compoent!</p>
- <child></child>
- </div>
- `,
- provide:{
- for:'test'
- },
- data(){
- return {
- message:'hello'
- }
- }
- })
- var App=new Vue({
- el:'#app',
- template:`
- <div>
- <parent></parent>
- </div>
- `
- })
3.$parent 和 $child
使用场景: 在父组件中可直接通过 this.$children 操作子组件, 子组件中可通过 this.$parent 修改父组件的值
- Vue.component('child',{
- props:{
- value:String, //v-model 会自动传递一个字段为 value 的 prop 属性
- },
- data(){
- return {
- mymessage:this.value
- }
- },
- methods:{
- changeValue(){
- this.$parent.message = this.mymessage;// 通过如此调用可以改变父组件的值
- }
- },
- template:`
- <div>
- <input type="text" v-model="mymessage" @change="changeValue">
- </div>
- })
- Vue.component('parent',{
- template:`
- <div>
- <p>this is parent compoent!</p>
- <button @click="changeChildValue">test</button>
- <child></child>
- </div>
- `,
- methods:{
- changeChildValue(){
- this.$children[0].mymessage = 'hello';
- }
- },
- data(){
- return {
- message:'hello'
- }
- }
- })
- var App=new Vue({
- el:'#app',
- template:`
- <div>
- <parent></parent>
- </div>
- `
- })
来源: http://www.bubuko.com/infodetail-2976386.html