2.2 vue基本使用
指令
插值 标签上的东西 {{}}之类
v-html 会有XSS风险,会覆盖子组件
computed 和 watch 的区别
缓存
在数据变化时执行异步或开销较大的操作时使用 watch
watch 观测的是 data 中数据在 created 后就会执行
计算属性 computed 所计算的属性受到多个属性影响 如购物车最后的结算金额
侦听属性 watch 所 watch 的属性影响多个属性
DOM 上用到的变量 都默认进入 watch(get、set) 我们只是添加方法
2.3 循环(列表)渲染
事件
event参数,自定义参数: 访问原始的 DOM 事件。可以用特殊变量 $event
事件修饰符,按键修饰符
事件被绑定到哪里
2.4 vue父子组件通讯
props和$emit
2.5 自定义事件 非父子组件间的通讯方式
2.6 vue父子组件生命周期调用顺序
父组件created,子组件created,子组件mounted,父组件mounted
父组件beforeUpdated,子组件beforeUpdated, updated,父组件updated,
2.8 自定义v-model
2.9 $nextTick
Vue是异步渲染-整合 data改变后 Dom不会立即渲染 $nextTick在Dom渲染后(updated)触发,以获取需要的数据
2.10 slot
基本使用:父组件向子组件c插入内容
scoped作用域 向父组件传递子组件的data
具名插槽
2.11 动态组件
2.12 异步(加载)组件
2.13 keep-alive
2.14 vue组件如何抽离公众逻辑
mixin 取不冲突的Property 生命周期的钩子函数内将一起执行
问题 变量来源不明确 不利于阅读
2.18 总结
3.2组件化基础
3.3 监听data变化的核心API是什么
vue响应式-视图响应数据变化
实现响应式的API 劫持了OBject.defineProperty 修改get、set方法
function observer( target) {
if (typeof target !== 'object' | | target === null) {
// 不是对 象或数组
return target
}
//重新定义各个属性(for in也可以遍历数组)
for (let key in target) {
def ineReactive(target, key, target [key])
}
}
function def ineReactive(target, key, value) {
//深度监听 从observer进来 ,递归
observer(value)
//核心API
0bject.defineProperty(target, key, {
get() {
return va Lue
},
set (newValue) {
if (newValue !== value) {
//设置新值
//注意,value一直在闭包中,此处设置完之后,再get时也是
value = newVa Lue
//触发更新视图
updateView() [- -手资源微信535950311 ) } }
缺点 : 深度监听,需要递归,一次性计算量大
无法监听新增、删除属性(不会走到defineProperty里),需要Vue.set Vue.delete
defineProperty是对象的方法,数组有自己的方法
3.5 vue如何监听数组的变化
//重新定义数组原型
const oldArrayProperty = Array. prototype
//创建新对象,原型指向0 ldArrayProperty ,再扩展新的方法不会影响原型
const arrProto = object. create( 0 LdArrayProperty)
[ 'push', 'pop','shift', 'unshift', 'splice']. forEach ( methodName =
arrP roto [methodName] = function () {
updateView( ) // 触发视图更新
0 LdAr rayP roperty [methodName] . call(this, ...argumerts)
}
})
function observer(target) {
if (typeof target !== 'object' I1 target === null) {
// 不是对 象或数组
return target
}
if (Array. isArray(target)) {
target._ proto___ =arrProto
}
从新定义了数组的方法,数组数据改变时,走新定义的,包含updateView的方法
3.6 虚拟DOM
JS模拟DOM结构
tag、prop、children
3.8 diff算法
优化时间复杂度到O(n)
key作用:tag和key相同,则认为是相同节点
vfor中为什么要用key
3.10 深入diff算法源码
patchVnode函数、addVnode、removeVnode、updateChildren函数
vdom核心概念很重要: h、vnode、 patch、 diff、 key等
3.14 模板编译
with语法使用
vue template complier将模板编译为render函数
执行render函数生成vnode
with语法
将{}内自由变量当成obj的属性来查找
正常找不到是undefined,with会报错
3.15 vue模板编译
template经过compiler执行 变成带with的JS代码
template编译成render函数
代码中_c 是vue自定义函数createELement缩写 _v是vue自定义函数createTextVNode缩写
_s是vue自定义函数toString缩写
- 模板编译为render函数,执行render函数返回vnode
- 基于vnode再执行patch和diff (后面会讲)
- 使用webpack vue-loader , 会在开发环境下编译模板(重要)
3.16 vue组件可用render替代template
3.17 组件渲染过程
- 响应式: 监听data属性getter setter (包括数组)
- 模板编译:模板到render函数,再到vnode
- vdom : patch(elem, vnode)和patch(vnode, newVnode)
3.18 vue组件如何渲染和更新
初次渲染过程
- 解析模板为render函数(或在开发环境已完成,vue-loader )
- 触发响应式,监听data属性getter setter
- 执行render函数,生成vnode,patch(elem, vnode)
Object.defineProperty()中包含getter和setter
更新过程
- 修改data,触发setter (此前在getter中已被监听)
- 重新执行render函数,生成newVnode
- patch(vnode, newVnode)
更新时watcher检测到data变动,触发setter->updateView(执行render函数,patch)
3.19 异步渲染
-
回顾$nextTick
-
汇总data的修改,一次性更新视图 虚拟DOM
-
减少DOM操作次数,提高性能
-
渲染和响应式的关系
-
渲染和模板编译的关系
-
渲染和vdom的关系
3.20 如何用JS实现hash路由
- hash 变化会触发网页跳转,即浏览器的前进、后退
- hash 变化不会刷新页面, SPA必需的特点
- hash 永远不会提交到server端(前端自生自灭)
location.href
window.onhashchange
3.21 如何用JS实现H5
histroy.pushState
window.onpopstate
4.1 vue真题演练
数据双向绑定
- input 元素的value = this.name
- 绑定input事件this.name = $event.target.value
- data 更新触发re-render
视图层的操作触发JS方法,引起data的改变
data必须是个函数
vue文件编译后是个类class 实例化时候 data数据会共享
ajax请求应该放在哪个生命周期
mounted
- JS 是单线程的, ajax异步获取数据
- 放在mounted之前没有用,只会让逻辑更加混乱
如何将组件所有props传递给子组件?
- $props
4.2 vue真题演练
何时需要使用beforeDestory
- 解绑自定义事件event.$off
- 清除定时器
- 解绑自定义的DOM事件,如window scroll等
Vue常见性能优化方式
- 合理使用v-show和v-if
- 合理使用computed
- v-for 时加key ,以及避免和v-if同时使用
- 自定义事件、DOM事件及时销毁
- 合理使用异步组件
- 合理使用keep-alive
- data 层级不要太深
- 使用vue-loader在开发环境做模板编译(预编译)
5.1 Proxy
Object.defineProperty的缺点
- 深度监听需要一次性递归
- 无法监听新增属性/删除属性 ( Vue.set Vue.delete )
- 无法原生监听数组, 需要特殊处理
开课吧
7
vue为什么要求组件模版只能有-个根元素
从三方面考虑:
- new Vue({el:' #app'})
2.单文件组件中,template下的元素div。其实就是"树”状数据结构中的"根"。
一个vue单文件组件就是一个vue实例, 如果template下有多个div那么如何指定vue实例的根入口呢,为了让组件可以正常生成一个vue实例, 这个div会自然的处理成程序的入口,通过这个根节点,来递归遍历整个vue树下的所有节点,并处理为Ndom,最后再渲染成真正的HTML,插入在正确的位置。
- df算法要求的,源码中,patch.js里patchVnode()。