在一个深度位置的对象当中寻找一个键值对,如果找到返回键值所在的路径,如果没有找到,则返回null。
const obj = { a: {b:2}, c: {d:3} } find(obj, 'd', 3); 返回 ['c', 'd'];
const find = (obj, key, value, arr = [-1]) => {
arr[0] += 1;
for (let i in obj) {
if (typeof obj[i] === "object") {
arr.push(i);
find(obj[i], key, value, arr);
} else if (obj[i] === value && i === key) {
arr.push(i);
break;
}
}
return arr.slice(-arr[0]);
};
console.log(find(obj, "e", 3));
vue3.0 新特性
双向绑定,Object.defineProperty()与proxy比较
- Object.defineProperty()缺点:
- 无法检测property的添加或移除,property必须在data对象上存在才能转换为响应式。
解决办法
Vue.set() / vm.$set() - 无法监听数组的变化。解决办法:底层实现了pop(),push(),shift(),unshift(),splice(),sort(),reverse()方法
- 无法检测property的添加或移除,property必须在data对象上存在才能转换为响应式。
解决办法
- Object.defineProperty()优点: IE9支持,兼容性好
- Proxy优点
- Proxy可以直接监听对象而非属性
- Proxy一次遍历即可,不需要深度遍历
- Proxy可以直接监听数组的变化
- Proxy有多种拦截方式:has,apply,ownkeys,deleteProperty
- Proxy返回的是一个新对象,对这个新对象操作即可。
- Proxy作为新标准将受到浏览器厂商的重点持续的性能优化
生命周期
beforeCreate / created / beforeUpdate / updated / beforeMount / mounted / beforeDestory / destoryed
data返回一个函数而不是对象,原因
因为对象地址复用,当两个元素都指向同一个对象时,修改其中一个会影响另一个,但是使用函数的话,每次函数调用,都会产生新的不同于上一个的对象,保证组件的不同实例有不同的data。
为什么computed不用返回一个函数,data为什么需要返回函数
computed计算属性,是基于响应式的依赖进行缓存的,他根据data选项中的数据进行计算,返回一个数值。基于组件的不同data衍生出来的computed自然不需要使用函数。
定义在data对象中的属性,可以使用this访问
- Vue源码之数据的代理访问
- 当写this.xxx的时候,vue通过Object.defineProperty()给this.xxx设置了一层代理,实际访问的是this._data里的xxx属性,而this._data指向的对象就是data对象。
computed与watch的区别及具体的使用场景
- computed:计算属性,有缓存,依赖数据进行计算时,使用
- watch:侦听属性,无缓存,观察和响应vue实例上的数据变动,异步操作或者开销较大的操作使用。
v-show与v-if的区别
- v-if是真正的渲染条件,因为它会确保在切换过程中条件内的事件监听器和子组件适当的被创建和销毁。
- v-if也是惰性的,在初始条件为false时,他什么都不做,直到第一次条件为真的才会渲染。
- v-show不管条件是什么,都会被渲染,他只是简单的进行css的切换。
- v-if有更高的切换开销,v-show有较高的初始渲染开销,频繁切换使用v-show,切换改变次数较少,使用v-if
v-show会触发生命周期么?触发哪几个
v-show通过控制css的display属性,来控制显示和隐藏,无论是false,还是true,在初始渲染的时候都会被渲染,且状态改变并不会导致元素的创建和销毁,所以,v-show无论是作用于元素还是组件,都不会影响组件(包括父组件)的生命周期。
v-if会触发生命周期么?触发哪几个
v-if是真正的渲染条件,且是惰性的,当他为false的时候,不会做任何渲染,也不会触发任何生性周期。 v-if作用域普通元素的时候,v-if值的改变对父组件的影响是使组件更新渲染,所以会触发beforeUpdate和updated函数。 v-if作用于组件时,对父组件的影响与上面一致,但对自身组件的影响:
- v-if 由false---true:触发beforeCreate,created,beforeMount,mounted
- v-if 由true---false:触发beforeDestory,destoryed
v-for为什么使用key
如果不使用key,vue会使用一种最大限度的减少动态元素并且尽可能尝试就地修改/复用相同类型的元素的算法,而使用key时,它会基于key的变化重新排列元素顺序并且会移除key不存在的元素。 它可以用于强制替换元素而不是重复使用它。1.完整的触发组件的生命周期钩子2.触发过渡
key为什么不能使用index
在做数组遍历批量生产子节点时,切记同层级的每个节点的key值不能重复并且不会改变。比如对数组元素进行操作时,当在数组元素中间增加一个元素时,其他数组元素的index会改变,那么使用index作为key值,则元素对应的key值就会改变,那么就会重新渲染,造成性能浪费,还可能出现bug。
vue 组件通信
- 父子组件通信:props/children/attrs/$listener
- 兄弟组件通信:eventBus; Vuex
- 跨级组件通信:eventBus; Vuex; provie/inject ; listener
父组件如何调用调用子组件的方法
子组件可以通过emit绑定一个自定义事件,当语句被执行时,就会将参数传递给父组件,父组件通过v-on监听hing接受参数。
this.$emit('childMethod',val)
v-on:childMethod = childMethod
ref的指向(DOM节点,自定义组件中)
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据
简单描述一下vuex
Vuex是Vue.js应用程序的状态管路模式,它采用集中式管理应用的所有组建的额撞他。vuex解决了多个视图依赖于同一状态和来自不同视图的行为需要变更同一状态的问题 Vuex的哥哥模块:
- state:用于数据的存储,是store中的唯一数据源。
- getter:如vue中的计算属性一样,基于state数据的二次包装,常用语数据的筛选和多个数据的相关计算。
- mutation:改变state中数据的唯一途径,且不能用于异步操作。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
- action:类似于mutations,用于提交mutation来改变状态,可以用来异步操作。Action 提交的是 mutation,而不是直接变更状态。
- mudule:类似于命名空间,用于项目中将各个模块的状态分开定义,便于维护。
react中有一个贯穿传递的思想,vue如何实现这个
provide / inject