Vue
组件间的通信
- 父传子:props
- 两种形式:数组、对象
- props 对象属性: type default validator required..
- 如果prop type是Array或者object default需要用函数返回**
- 子传父:自定义事件
//子组件的单Vue文件内
methods:{
...
xxx(){
...
this.$emit('choose-something',value)
...
}
...
}
//父组件内
# template
<div>
<Son @choose-something="yyy" ></son>
</div>
# methods
yyy(e){
console.log(e)//e就是子组件内触发事件提供的value
...
}
关于自定义事件命名-记住不要用驼峰命名方式。记一次踩坑:
刚开始以为是异步问题,弄了N个demo测试,发现即使是子组件异步触发的事件,父组件也会异步获取。
后来再检查N次代码,发现是命名原因。 这一点在官方文档有说明:我们推荐你始终使用 kebab-case 的事件名。
- 兄弟通信:eventBus
在兄弟的父亲定义一个bus,作为数据传递的介质,然后每个兄弟都inject
一下,建立连接。
example:
# father
export default{
data(){
return{
eventBus:new Vue()
}
},
provide(){
return {
eventBus: this.eventBus
}
}
}
# son
export default{
inject:['eventBus']
}
- 利用slot-scope进行通信
如 popover组件里,本来popover的关闭函数是在popover内部使用,但后来有一个需求就是:我外部点击一个button后,同样可以关闭这个popover。
于是利用slot-scope,提取里面的close函数。
<w-popover position="top">
<div slot="content" slot-scope="{close}">
这是popover内容
<w-button @click="close">关闭</w-button>
</div>
<w-button class="button">向上</w-button>
</w-popover>
- vuex
每一个Vuex应用的核心就是 store(仓库)。
Vuex 和单纯的全局对象有以下两点不同:- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
全局对象需要将值传递到相应的子组件之后,才会发生更新 - 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
state、mutations、action、getter
辅助函数
computed: mapState(),mapGetters(), //响应的
methods: mapMutations(),mapActions()
获取状态对象: store.state
触发状态变更: store.commit('xxx') //xxx 是mutations里面的函数
computed 、 watch 、 methods 的不同
computed的函数所依赖的响应式属性发生了变化,则函数会执行产生新的结果,结果会被缓存,直到下一次执行更新结果。
watch 侦听器 侦听props/data 的数据变化。
methods 事件处理器 一般执行函数放在这里
computed与methods的区别
- computed是响应式的,methods并非响应式。
- 调用方式不一样,computed定义的成员像属性一样访问,methods定义的成员必须以函数形式调用。
- computed是带缓存的,只有其引用的响应式属性发生改变时才会重新计算,而methods里的函数在每次调用时都要执行。
- computed中的成员可以只定义一个函数作为只读属性,也可以定义get/set变成可读写属性,这点是methods中的成员做不到的
$refs
、$ parent
、$children
、$slots
- ref --- 给元素或子组件注册引用信息,然后父亲可以通过
this.$refs.xxx
来访问当前子组件/元素。
ref指向的是DOM实例,因此只有当子组件渲染完成之后才可以访问。并且!ref不是响应式的,只能记录下当时访问的结果。
——你应该避免在模板或计算属性中访问$refs
。
- parent、children
在组件中可以通过这两个API来修改/访问相应的父组件/子组件。
深入响应式原理
Vue实现数据的响应:把一个普通 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
Object.defineProperty(obj,prop,descriptor) ----添加或修改Obj上的属性(prop)
descriptor---对象的属性描述符有两种类型:数据描述符、存取描述符。(ES5之后)
- 数据描述符:具有值的属性
- 存取描述符:由getter-setter函数对描述的属性。
注意: data 对象属性如果是动态添加的,一定不能直接赋值。 因为 Vue 不能检测到对象属性的添加或删除。
两种方法:
- 先动态添加完成后(对数据处理之后),再重新赋值。[本质上赋值的是一个新对象]
- 使用vue.set()
参考资料:vue中遇到的坑 --- 变化检测问题(数组相关)
题外话:关于Vue与React
Vue框架更多是对DOM操作的一些封装,利用Object.defineProperty转换数据为getter/setter,(可以监测到状态数据的变化),再用数据去驱动UI(DOM)的改变。
而React的实现是用虚拟DOM去映射真正的DOM,每一次数据的变化,实际是更新了虚拟DOM。React会对虚拟DOM进行脏检查。所以每一次state的对象赋值更新,需要是一个新的对象。