在编写一个vue项目的时候,组件之间的数据通信是必不可少的。也是非常的重要的一步。今天写几种vue中组件的数据通信方式以及应用场景。
props&@
-
props
父组件把数据通过v-bind这个指令绑定在子组件参数上传下去.子组件在props这个属性获取.
props可以以数组和对象的形式接收.如下-
数组形式
// 父组件 <Children v-bind:msg="msg"></Children> // 在子组件上定义 props: ["msg"] //字符串对应的是父组件绑定的v-bind值.
-
对象形式
// 父组件 <Children v-bind:msg="msg"></Children> // 在子组件上定义 -- 对象可以设置其他条件 props: { msg: { type: String, //判断传入的类型 default: "默认数据", //默认值 require: true, // 是否必须传入项 }, },
子组件只能使用不能直接修改props的属性.直接修改的话修改成功并且vue会抛出警告,所以不推荐你这么做.
-
-
@
父组件传入一个方法给子组件.子组件可以调用这个方法修改父组件的值(解决了子组件不能修改父组件的值)。
// 在父组件把定义好的fn传下去,供子组件调用. <Children @fn="fn"></Children> //子组件通过$emit调用fn. this.$emit("fn", 1, 2, 3);
ref
在父组件注册的子组件中添加ref属性.父组件能通过this.$refs.属性名拿到这个子组件的实例.就可以直接做操作啦.
//父组件
<Children ref="subInst" />
this.$refs.subInst // 父组件可以通过这个方法直接拿到子组件的data和methods.
provide&inject
在父组件提供数据(provide),子组件注入数据(inject).
provide 选项应该是:一个对象或返回一个对象的函数
inject 选项应该是:一个字符串数组,或 一个对象,对象的 key 是本地的绑定名
//父组件上添加这个方法
provide() {
return {
msg: this.msg, // 这里需要注意传基本的值,没有响应式.需要传一个响应式的对象.
};
},
// 子(孙)组件
inject: ["msg"],
官方着重说明provide 和 inject 主要为高阶插件/组件库提供用例,并不推荐直接用于应用程序代码中。
KaTeX parse error: Expected 'EOF', got '&' at position 6: attrs&̲listeners
这两个属性是一个对象.分别保存父组件中传下来的数据和方法.
-
$attrs
//父组件 <Children :msg="msg"></Children> //子组件 //传下来的数据保存在$attrs这个属性中 <template> <div class="hello"> 我是attrs子组件 --- {{ $attrs.msg }} //$attrs上的值是只读的,并不会响应式的。强制$set设置vue会抛出警告.这是一个只读属性. </div> </template>
-
$listeners
//父组件 <Children :fn="fn"></Children> //子组件 //传下来的方法保存在$listeners这个属性中,可直接调用. <template> <div class="hello"> 我是attrs子组件 --- {{ $attrs.msg }} </div> </template>
sync&model
这是vue组件中自带的语法糖。方便调用。
-
sync
//父组件 <Children :msg.sync="msg"></Children> // 在父组件注册的子组件挂载修饰符.sync // 子组件 this.$emit("update:msg", "789"); //子组件上直接调用这个方法,传值改值.
.sync修饰符相当于vue在内部定义方法可以修改值,相当于父组件上使用@把函数传下来这种.
在子组件打印实例,会发现在listen上出现update:msg方法。 -
model
//父组件 <Children v-model="msg"></Children> // 在父组件注册的子组件v-model //子组件上使用需要props接收value和调用事件event的this.$emit("input", value); //这里默认使用input的v-model <input type="text" v-model="value" /> //子组件直接修改前提的接收props的value.
v-model用于表单数据的双向绑定,这个背后就做了两个操作:
1. v-bind绑定一个value属性
2. v-on指令给当前元素绑定input事件在子组件可以通过model修改默认的value和event.例
model: { prop: "check", event: "change", },
注意咋组件上调用v-model还是需要你去绑定值和修改 值得操作.
eventBus
通过创建一个新的vue实例,当做事件车然后挂在vue的原型上。通过发布订阅的方式就行通讯。这个方法可任意组件之间使用,前面的但是父组件传下来的。
//任意组件创建订阅callback这个方法,
this.$eventBus.$on("callback", (data) => {
console.log("接收到data----", data);
});
//任意组件上传入数据通讯,(发布)
this.$eventBus.$emit("callback", "传入数据");
使用这个方法可以在任意两个组件上进行通讯。方便至极。缺点是项目复杂的是时候难以维护,追踪。
parent&children
通过挂载在Vue的原型上,递归执行$emit方法.在需要通讯的组件上订阅发布.
-
parent
Vue.prototype.$dispatch = function (eventName, params) { var parent = this.$parent; while (parent) { parent.$emit(eventName, params); parent = parent.$parent; } } //在原型上定义个方法,内部就是一直往上级执行$emit这个方法.
// 在需要使用组件数据的父组件中,订阅. this.$on("Up", function (params) { this.msg = params; }); // 调用方法的子组件或孙组件. this.$dispatch("Up", "我是通过parent方式改变的数据");
-
children
// 通知子组件的监听事件 Vue.prototype.$notice = function (eventName, params) { var children = this.$children; function deep(children) { children.forEach(item => { item.$emit(eventName, params); if (item.children) { deep(children); } }); } deep(children); } //在原型上定义个方法,内部就是递归调用下级的$emit这个方法.
// 在需要使用组件数据的子组件中,订阅. this.$on("down", function (params) { this.msg = params; }); // 调用方法的组件 this.$notice("down", "我是通过children方式改变的数据");
这两种写法一般在封装组件中用的比较多.好处就是能一直往上级查找或者往下查找.缺点就是污染Vue原型.
solt
这种写法是在父组件中使用子组件的数据.也称之为作用域插槽.
(solt的其它用法就不说了需要的去官网直接瞄一瞄).
// 父组件
<children>
<template v-slot:header="scope">
<h1>{{scope.header}}</h1> //这里展示的就是123.
</template>
</children>
//子组件
<slot name="header" :header="123"></slot>
比如element的表格可编辑内容就是这个作用域插槽实现的.有兴趣的可以去看看源码.
vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式
vuex可以说是这几种中数据管理最好的了. 最主要的是响应式(基于vue),组件之间数据共享.
这里就略过一下api吧.毕竟这个东西用vue的基本使用到这个东西.大家都很熟.
-
state
存储数据的属性, 不可直接修改state的属性值.(不方便追踪)
-
mutations
同步修改state的方法,通过commit触发
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state,a) { //后面是传进来的参数. // 变更状态 state.count++ } } }) // 触发 store.commit("increment",2)
-
actions
-
Action 提交的是 mutation,而不是直接变更状态。
-
Action 可以包含任意异步操作。
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment') } } }) //触发 store.dispatch("increment"); // 这里需要异步操作返回promise.
-
-
getters
相当于vue中计算属性computed.
const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) } } }) //访问 store.getters.doneTodos
-
modules(略)
-
辅助函数
- mapState
- mapActions
- mapMutations
- mapGetters
返回的是函数,参数是在vuex定义对应的属性名的数组. 返回一个对象.
总结
以上就是自己对vue数据通讯的总结. 如果觉得文章对你有用,欢迎给个“赞”,也欢迎技术讨论,感谢大家 !