常用:props/$emit
父传子:
通过props向子组件传值。调用子组件时,可以用 静态传递 或者 使用 v-bind动态传递,子组件用props接受使用。
子传父:
通过$emit方法触发自定义事件。子组件通过this.$emit方法触发父组件上(调用子组件的那个语句)自定义事件,将值传递给自定义事件函数,通过$event获取。
其他:
v-model
子组件中,props中通过value字段来接收
子组件触发this.$emit(‘input’)事件,父组件改变v-model绑定的值
所以在组件中使用的时候,相当于下面的简写:
这通常用在子组件是表单元素的情况,例如调用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、接受事件组件内
以上方法适合两个或不多的组件之间传值,如果有以下情况:
多视图依赖同一个状态不同的视图需要变更同一个状态用上面的方法虽然可以实现,但是会造成状态管理混乱,这种情况需要一个多组件共享的响应式数据管理中心,在此来实现一个简易版的:
数据共享中心: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:
简易手写版:
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}