事情发生在上周(2019-06-06)团队技术分享的时候。
原由在于一个问题:vue 中多个组件如何使用同一个变量,咱们叫这个变量为 baseConfig
吧。
说实话我没想到那么多人不理解其中的知识。今天我整理一下发出来。html
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 能够帮助咱们管理共享状态,并附带了更多的概念和框架。这须要对短时间和长期效益进行权衡。前端
状态自管理应用包含如下几个部分:vue
如下是一个表示“单向数据流”理念的简单示意:vuex
其实看完了上面的介绍,咱们就明白,这是一个很是符合咱们需求的工具。那么咱们就来看看怎么去应用。编程
mapState
辅助函数 当一个组件须要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,咱们可使用 mapState 辅助函数帮助咱们生成计算属性。store
中获取的。这样在经过 mutations
等方式改变以后,咱们的值也会动态更新。const store = new Vuex.Store({ state: { baseConfig: { server_name: 'lilnong.top' } } }) // 建立一个 User 组件 const Serv = { template: `<div>{{ server_name }}</div>`, computed: { server_name() { // this.$store return store.state.baseConfig.server_name } } } const app = new Vue({ el: '#app', store, // 这样能够把 store 的实例注入全部的子组件 components: { Serv }, template: ` <div class="app"> <serv></serv> </div> ` })
baseConfig
须要定义在最外面,而后给全部的子组件都传递进去,当有改变的时候,子组件也会跟着改变。数组
{ data: { baseConfig: { server_name: 'lilnong.top' } } } <child :server_name="baseConfig.server_name" :baseConfig="baseConfig">
每一个子组件都须要接收。微信
{ props:['server_name', 'baseConfig'],//这种是无默认值,无类型检查的,正常使用不推荐这种写法 }
该方案也叫方案二,并非我写错了,是由于他们的场景是同样。
在 Vue Router 的路由中,咱们把组件配置在 routes
中,致使咱们没法在模板之中传递参数。
这里咱们须要使用他提供的 props
属性来传参,文档地址。jsRun测试地址。lilnong.top测试地址app
const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' } const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] const router = new VueRouter({ routes // (缩写) 至关于 routes: routes }) const app = new Vue({ router }).$mount('#app')
<div id="app"> <h1>Hello App!</h1> <p> <router-link to="/foo">Go to Foo</router-link> <router-link to="/bar">Go to Bar</router-link> </p> <router-view></router-view> </div>
就是以下使用,定义一个全局对象,而后修改这个全局对象就行了异步
const sourceOfTruth = {} const vmA = new Vue({ data: sourceOfTruth }) const vmB = new Vue({ data: sourceOfTruth })
原理上来说,仍是全局对象,可是经过简单的规定,来明确数据流向
var store = { debug: true, state: { message: 'Hello!' }, setMessageAction (newValue) { if (this.debug) console.log('setMessageAction triggered with', newValue) this.state.message = newValue }, clearMessageAction () { if (this.debug) console.log('clearMessageAction triggered') this.state.message = '' } } var vmA = new Vue({ data: { privateState: {}, sharedState: store.state } }) var vmB = new Vue({ data: { privateState: {}, sharedState: store.state } })
好了,三种方案这里就已经介绍完了。那开始看看咱们的争论:全局放个对象的方式不行(对方观点),数据更新时组件不会自动更新
vue 数据绑定的原理你们都懂吧?经过 defineProperty
来劫持,Dep
收集依赖等等。
对于对象类型的数据,咱们变量里面保存的实际上是一个指向堆的地址,咱们来看下面的这个例子。
var obj = {};//定义了一个对象,`obj` 存放的是一个地址 obj.a = 1;//经过 `obj` 的地址,找到对象,而后给对象里面放了 `a=1` ; var obj1 = obj;//把 `obj` 的地址,给 `obj1` 复制了一下 obj1.a = 2;//经过 `obj1` 的地址,找到对象,而后给对象里面放了 `a=2` ; //这个时候,对象里面存放的就是{a:2}//console.log(obj, obj1) //这里引出了另外一个问题 深拷贝与浅拷贝
这里也就是个人核心原理。
是否是看到上面的原理好简单?可是每每不是这么简单,下面我们分析一下状况
null
、 undefined
对象覆盖,就是以下的这个赋值场景。
其实我理解你是想给 obj
从新都赋值一下。
obj={}; obj2 = obj; obj.a = 1; obj2 = {a:2,b:3};//这里把 obj2 的地址换成了新的一个对象 //console.log(obj, obj2)
可是不能这样写,正确操做以下:
Object.assign(obj2, {a:2,b:3})
obj2.a=2;obj2.b=3;
后添加的属性,没有计入 vue
的数据观察队列(新手常常犯的错误)
于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 如今是响应式的 vm.b = 2 // `vm.b` 不是响应式的
对象解决方案 Vue.set(object, propertyName, value)
对象解决方案(实例内) this.$set(object, propertyName, value)
数组更新检测
将一些方法进行了封装 push()、pop()、shift()、unshift()、splice()、sort()、reverse()
。
经过上面的方法来改变数组能够监听到改变。
因为 JavaScript 的限制,Vue 不能检测如下数组的变更:
vm.items[indexOfItem] = newValue
vm.items.length = newLength
共享数据三种方法
对象引用须要注意的地方
obj2={}
Array
与 Object
。String
与 Null
等不包括在内增长数据要注意是否被观察到
Vue.set
测试地址,采用 setTimeout 来模拟异步操做。当时苦的一批,完了还没保存。性感码农,在线编程。
成功的说服了在场的兄弟们,而后周四就拖堂了。