首页 > 编程知识 正文

vue组件通信方式及原理,vue组件通信有哪几种方式

时间:2023-05-04 18:37:46 阅读:195314 作者:2292

组件通信方式 父子组件通信

常用:props/$emit
父传子:
通过props向子组件传值。调用子组件时,可以用 静态传递 或者 使用 v-bind动态传递,子组件用props接受使用。

子传父:
通过$emit方法触发自定义事件。子组件通过this.$emit方法触发父组件上(调用子组件的那个语句)自定义事件,将值传递给自定义事件函数,通过$event获取。

其他:
v-model
子组件中,props中通过value字段来接收
子组件触发this.$emit(‘input’)事件,父组件改变v-model绑定的值
所以在组件中使用的时候,相当于下面的简写:

<custom v-bind:value="something" v-on:input="something = $event.target.value"></custom>

这通常用在子组件是表单元素的情况,例如调用elment-ui中的el-input等组件时。

.sync修饰符
允许props进行双向绑定,以this.$emit(update:PropName,newValue)的模式触发事件。

即:

<text-document v-bind:title.sync="doc.title"></text-document>

相当于:

<text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event"></text-document>this.$emit('update:title', newTitle)

通常用在父子组件都需要改变传入值的情况,比如:在调用el-dialog的时候,visible属性支持.sync修饰符是为了子组件中右上角叉号点击时能改变父组件中visible的绑定值,这样就能关闭dialog。

this.$refs(不推荐使用,容易造成状态混乱)
首先你的给子组件做标记。demo :
然后在父组件中,通过this.$refs.one就可以访问了这个自组件了,包括访问子组件的data里面的数据,调用它的函数。
this.refs如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例

无直接关系组件间通信

常用:bus总线事件 原理可以参考:https://blog.csdn.net/bingqise5193/article/details/109406910
与this.$emit原理一致,都是在同一个vue实例内实行的,只不过放在了一个新的vue内,同样是利用了vm.$on/vm.$off/vm.$emit接口来实现的。
1、let bus = new Vue({})
2、Vue.prototype.Bus = bus
3、触发组件内 this.Bus.emit(‘userdifined’, ‘chufa’)
4、接受事件组件内

mounted () {this.Bus.$on('userdifined', res => console.log(res))},destroyed () {this.Bus.$off('userdifined')} 简易集中式状态管理器

以上方法适合两个或不多的组件之间传值,如果有以下情况:

多视图依赖同一个状态不同的视图需要变更同一个状态

用上面的方法虽然可以实现,但是会造成状态管理混乱,这种情况需要一个多组件共享的响应式数据管理中心,在此来实现一个简易版的:

数据共享中心:store.js

export default { state: { data: 0 }, change(r) { this.state.data += r }}

调用:

<template> <div> <h1>componentA</h1> <div>{{data.data}}</div> <button @click="change(1)">click to change</button> </div></template><script>import store from '@/state/store'export default { data() { return { // 应该要给一个对象,不能store.state.data // store.state.data为一个基础类型,赋值后,当store.state.data变更时与data并无关系 // 而store.state是一个对象,赋值为地址赋值,data与store.state指向同一个对象,才能触发响应式 data: store.state } }, methods: { change(data) { store.change(data) } }}</script>

建立一个状态管理中心,用于管理所有共用的状态,并且如果改变这些状态必须通过中心的事件来更改,这样就能记录更改状态的所有操作。

vuex的使用 vuex是什么

一个集中式存储管理所有组件的状态,当多个组件均需要使用或改变这个状态时,适合用vuex。Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地更新。例如用户信息、菜单信息、购物车信息很适合用vuex来实现

vuex的使用步骤 1. 安装插件: npm i vuex -S2. 载入插件:import Vuex from 'vuex'3. 注册插件:Vue.use(Vuex)4.实例化存储对象:const store = new Vuex.Store({ modules: { count, msg }})5. 挂载:new Vue({ store, render: h => h(App),}).$mount('#app')6. 使用存储对象import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'computed: { ...mapState({ msg: state => state.msg.msg, count: state => state.count.count }), ...mapGetters(['reversedMsg']) }, methods: { ...mapMutations(['changeCount']), ...mapActions(['changeCountAsync']) },

Tips:

具体的使用请参考vuex官方文档更改state的操作必须通过commit mutations中的操作,mutations中只能有同步操作,这样dev tools能够记录回溯每次状态更改的情况,actions中可以有异步操作。actions中的第一个参数为context,但并不是实例,context对象包括以下:
vuex使用实战-购物车例子

具体的项目代码请查看:shop-cart
几个小TIPS:

find/findIndex/filter/reduce/every的使用,reduce常用于求和import/export,具体参考:localStorage只能存储字符串,因此存储和取用对象时要注意 JSON.parse(window.localStorage.getItem('cart-goods')) window.localStorage.setItem('cart-goods', JSON.stringify(state.goods)) 作用域插槽:父组件只能访问父组件中的值,如果想要访问子组件中的值,则可以通过v-slot来实现:在父组件中引用子组件的行信息 <el-table-column prop="address" label="操作"> <template v-slot="scope"> <el-button @click="addProducts(scope.row)">加入购物车</el-button> </template> </el-table-column> 基于其他的值计算并响应式更改,请用vuex中的getters,另外,所有更改state的操作都要通过提交mutations。如果某个操作需要在每次 mutation 之后调用,可以使用store的plugin,使用如下: const myPlugin = store => { // 当 store 初始化后调用 store.subscribe((mutation, state) => { // 每次 mutation 之后调用 // mutation 的格式为 { type, payload } // localStorage只能存储字符串 window.localStorage.setItem('cart-goods', JSON.stringify(state.goods)) })} export default new Vuex.Store({ plugins: [myPlugin], state: {}} 在表单元素中,如果绑定的是vuex中的值,要用:value去绑定,不能用v-model,更改vuex中的值需要通过mutations,因此采用:value+@change等事件去使用,实现双向绑定。对于change等事件,sxdbmh传递了自定义参数的时候,还想得到原来那个默认参数,就手动传递一个 $event vuex原理

简易手写版:

let _Vue = nullclass Store { constructor(options) { const { state = {}, getters = {}, mutations = {}, actions = {} } = options this.state = _Vue.observable(state) this.getters = Object.create(null) Object.keys(getters).forEach(key => { Object.defineProperty(this.getters, key, { get: () => getters[key](state) }) }) this._mutations = mutations, this._actions = actions } commit (type, payload) { this._mutations[type](this.state, payload) } dispatch (type, payload) { this._actions[type](this, payload) }}function install (Vue) { _Vue = Vue // 挂载$store _Vue.mixin({ beforeCreate() { if(this.$options.store){ // 如果是组件则不需要 _Vue.prototype.$store = this.$options.store } } })}export default { Store, install}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。