VUE 组件通信以及组件的数据双向绑定

目录

简介

示例

父子组件通信

兄弟组件通信

跨级组件通信

全局组件通信

$attrs / $listeners

$parent / children / ref

v-model / .sync(不常用)

简介

Vue组件通信是指不同组件之间进行数据传递、事件触发等交互操作的过程。

在Vue中,有以下几种常用的组件通信方式:

  • 父子组件通信
  • 兄弟组件通信
  • 跨级组件通信
  • 全局组件通信
  • $attrs / $listeners
  • $parent / children / ref
  • v-model / .sync

示例

父子组件通信

父子组件通信: 父组件通过props将数据传递给子组件,子组件通过emit触发事件向父组件传递数据。

父组件:

<template>
  <div>
    <child-component :message="message" @update-message="updateMessage"></child-component>
  </div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';

export default {
  data() {
    return {
      message: 'Hello Vue!'
    };
  },
  methods: {
    updateMessage(newMessage) {
      this.message = newMessage;
    }
  },
  components: {
    ChildComponent
  }
};
</script>
 

子组件:

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="sendMessage">Send Message</button>
  </div>
</template>
<script>
export default {
  props: ['message'],
  methods: {
    sendMessage() {
      this.$emit('update-message', 'New Message');
    }
  }
};
</script>
 

兄弟组件通信

兄弟组件通信:通过共享状态管理工具(如Vuex)或者事件总线方式实现兄弟组件之间的通信。

共享状态管理工具示例(使用Vuex):

// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    message: 'Hello Vue!'
  },
  mutations: {
    updateMessage(state, newMessage) {
      state.message = newMessage;
    }
  }
});
 

组件示例:

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="sendMessage">Send Message</button>
  </div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';

export default {
  computed: {
    ...mapState(['message'])
  },
  methods: {
    ...mapMutations(['updateMessage']),
    sendMessage() {
      this.updateMessage('New Message');
    }
  }
};
</script>
 

跨级组件通信

跨级组件通信:通过provide/inject方式实现跨级组件之间的通信。

祖先组件示例:

<template>
  <div>
    <child-component></child-component>
  </div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';

export default {
  provide() {
    return {
      message: 'Hello Vue!'
    }
  },
  components: {
    ChildComponent
  }
};
</script>
 

子组件示例:

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>
<script>
export default {
  inject: ['message']
};
</script>
 

全局组件通信

全局组件通信:通过Vue实例的$emit/$on方法来触发和监听全局事件。

示例:

// main.js
import Vue from 'vue';

export const bus = new Vue();

// Component A
import { bus } from './main.js';

export default {
  methods: {
    sendMessage() {
      bus.$emit('update-message', 'New Message');
    }
  }
};

// Component B
import { bus } from './main.js';

export default {
  mounted() {
    bus.$on('update-message', (newMessage) => {
      this.message = newMessage;
    });
  }
};
 

$attrs / $listeners

$attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 interitAttrs 选项一起使用。

$listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件

父组件:

<template>
  <div>
    <h2>祖先组件</h2>
    <child-com1
      :f="f"
      :b="b"
      :c="coo"
      :d="d"
      title="data"
    ></child-com1>
  </div>
</template>
<script>
import "./childCom1.vue";
export default {
  components: { childCom1 },
  data() {
    return {
      f: "Javascript",
      b: "Html",
      c: "CSS",
      d: "Vue"
    };
  }
};
</script>

儿子组件:

<template class="border">
  <div>
    <p>f: {{ f }}</p>
    <p>childCom1的$attrs: {{ $attrs }}</p>
    <child-com2 v-bind="$attrs"></child-com2>
  </div>
</template>
<script>
import "./childCom2.vue";
export default {
  components: {
    childCom2
  },
  inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
  props: {
    f: String // f作为props属性绑定
  },
  created() {
    console.log(this.$attrs); // { "b": "Html", "c": "CSS", "d": "Vue", "title": "data" }
  }
};
</script>

孙子组件

<template>
  <div class="border">
    <p>b: {{ b }}</p>
    <p>childCom2: {{ $attrs }}</p>
    <child-com3 v-bind="$attrs"></child-com3>
  </div>
</template>
<script>
import "./childCom3.vue";
export default {
  components: {
    childCom3
  },
  inheritAttrs: false,
  props: {
    b: String
  },
  created() {
    console.log(this.$attrs); // { "c": "CSS", "d": "Vue", "title": "data" }
  }
};
</script>

$parent / children / ref

$parent / children / ref: 这几种方式都是直接得到组件实例,使用后可以直接调用组件的方法或访问数据,这里采用ref示例。

父组件

<template>
  <component-a ref="comA"></component-a>
</template>
<script>
  export default {
    mounted () {
      const comA = this.$refs.comA;
      console.log(comA.title);  // Vue.js
      comA.sayHello();  // 弹窗
    }
  }
</script>

子组件

export default {
  data () {
    return {
      title: 'Vue.js'
    }
  },
  methods: {
    sayHello () {
      window.alert('Hello');
    }
  }
}

v-model / .sync

v-model是 Vue.js 提供的一个语法糖,用于简化表单元素的双向绑定,它在内部实际上是使用了 :value 和 @input 这两个指令的结合形式。

v-model缺点:如需自定义传值,子组件内书写$emit('input', data) 因为名称固定为input所以单个组件只能使用一次。

.sync避免了v-model的这个问题可以自定义命名。

vue3取消了.sync这种语法,使用v-model:title 语法代替

v-model父组件:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <!--<router-view/>-->
    <car v-model="index"></car>
    <div>{{index}}</div>
  </div>
</template>
 
<script>
import Car  from "./car.vue"
export default {
  data(){
    return{
      index:0
    }
  },
  name: 'App',
  components:{Car}
}
</script>

v-model子组件:

<template>
  <div @click="$emit('input',value+1)">汽车</div>
</template>
<script>
  export default{
    props:["value"]
  }
</script>

 .sync父组件:

<template>
 <div>
   <h1>父组件:{{childSubTitle}}</h1>
   <Child :subTitle.sync="childSubTitle"></Child>
 </div>
</template>
 
<script>
import Child from './child.vue'
export default {
  data() { 
    return {
      childSubTitle:'数据',
    } 
  }, 
  components:{
    Child
  }, 
}
</script> 

.sync子组件:

<template>
  <div class="child">
    <h4>{{subTitle}}</h4>
    <button @click="changeSubTitle">改变</button>
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      newSubTitle:'测试数据'
    };
  },
  props: {
    subTitle:{
      type:String,
      default:'',    
    }
  },
  methods:{
    changeSubTitle(){
      this.$emit('update:subTitle',this.newSubTitle)
    },
  },
};
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值