不只是vue,react中在执行列表渲染时也会要求给每个组件添加上key这个属性。
要解释key的作用,需要先介绍一下虚拟DOM的Diff算法了。
我们知道,vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。
vue和react的虚拟DOM的Diff算法大致相同,其核心是基于两个简单的假设:
两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
同一层级的一组节点,他们可以通过唯一的id进行区分。
基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从O(n^3)降到了O(n)。
当页面的数据发生变化时,Diff算法只会比较同一层级的节点:
如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。
如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。
当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。
所以key的作用主要是为了高效的更新虚拟DOM
详细分析
Created实例初始化 也没并没有渲染 mounted 页面渲染完成
vue是异步渲染,data改变后,Dom不会立刻渲染
$nextTick会在Dom渲染之后被触发,获取最新Dom节点
自定义v-model
$nextTick
slot
动态、异步组件
keep-alive
minxin
父组件
<template>
<div>
<!-- 自定义v-model -->
<p>{{name}}</p>
<custom v-model="name" />
</div>
</template>
<script>
import custom from './Custom'
export default {
components: {
custom
},
data () {
return {
name: '张三'
}
}
}
</script>
子组件:
<template>
<input type="text"
:value="text"
@input="$emit('change',$event.target.value)">
</template>
<script>
export default {
model: {
prop: 'text',
event: 'change'
},
props: {
text: String,
default () {
return ''
}
}
}
</script>
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
简单理解:当数据更新了,在dom中渲染后,自动执行$nextTick函数,
slot详细分析
有的时候,在不同组件进行动态切换是非常有用的
可以通过Vue种的元素加一个特殊的is属性来实现:
<!-- 组件会在 `组件名` 改变时改变 -->
<component v-bind:is="组件名"></component>
根据 v-bind:is=“组件名” 中的组件名去自动匹配组件,如果匹配不到则不显示。
面试常见性能优化之一:异步组件
当组件体积非常大,通过异步组件
异步组件就是定义的时候什么都不用做,只在组件组要渲染的时候进行加载渲染并缓存
Vue实现按需加载,官方推荐使用结合webpack的代码分割功能进行。定义为异步加载的组件,在打包的时候,会打包成单独的js文件存储在static/js文件夹里面,在调用时使用ajax请求回来插入到html中。
同步组件和异步组件引入的区别
<script>
import helloWord from './helloWord '
export default {
components: {
FormDemo: () => import('./helloWord ')
}
}
</script>
<script>
export default {
components: {
helloword
}
}
</script>
动态组件和异步组件
vue如何缓存组件
面试常见性能优化之一:keep-alive
当在组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题,为了解决这个问题,我们可以使用元素将其动态组件包裹起来
<!-- 失活的组件将会被缓存!-->
<keep-alive>
<component v-bind:is="组件名"></component>
</keep-alive>
多个组件有相同的逻辑,抽离出来
创建一个js文件myMixin.js
export default {
data() {
return {
name: 'mixin'
}
},
created() {
console.log('mixin...', this.name);
},
mounted() {},
methods: {}
}
在组件中引入
<script>
import myMixin from './myMixin'
export default {
minxins: [myMixin],//可以添加多个,会自动合并起来
}
</script>
minxin并不是完美的解决方案,会有一些问题
minxin存在的问题:
vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
路由模式(hash、H5 history)
后者需要serve端支持,因此无特殊需求可选择前者
路由配置(动态路由、懒加载)
特点:Computed 有缓存,data不变则不会重新计算
Deep:true 实现深度监听
Watch 监听引用类型,拿不到oldVal
Event.proto_.constructor 原生的event对象
Event.target 事件挂载位置
Vue 中的event是原生的 事件被挂载到当前元素
传统组件,只是静态渲染,更新还要依赖于操作DOM
数据驱动试图-Vue MVVM 更多的是操作数据
Model-View-ViewModel的缩写
Model: 模型 View: 视图 ViewModel: 作为视图的模型,为视图服务
核心: API Object.defineProperty
Object.defineProperty 缺点
Vue3.0使用proxy实现响应式
Peoxy兼容性不好
通过Object.defineProperty 中的get 和set可以实现监听
API Object.defineProperty 不具备监听数组能力,需要自己实现
重新定义数组原型,创建新对象,原型指向原型,在扩展新的方法不会影响原型
DOM操作耗时耗费性能,js执行比较快
解决方案:把计算转移为js计算,因为js执行速度很快
vdom - 用js模拟DOM结构,计算出最小的变更,操作DOM
遵循规律:tag:标签 props: 属性 children:子元素
编译模板为render模板,执行render函数返回vnode
基于vnode再执行 patch 和 diff
使用webpack vue-loader,会在开发环境下编译模板
定义的vue组件是一个类,每个组件使用的时候相当于对类的实例化