vue

158 阅读5分钟

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

JS模拟DOM结构.png

3.8 diff算法

优化时间复杂度到O(n)

优化事件复杂度.png

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会报错

with语法.png

3.15 vue模板编译

template经过compiler执行 变成带with的JS代码

template编译成render函数

template执行结果.png

代码中_c 是vue自定义函数createELement缩写 _v是vue自定义函数createTextVNode缩写

_s是vue自定义函数toString缩写

vue源码缩写函数.png

  • 模板编译为render函数,执行render函数返回vnode
  • 基于vnode再执行patch和diff (后面会讲)
  • 使用webpack vue-loader , 会在开发环境下编译模板(重要)

3.16 vue组件可用render替代template

render替代template.png

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)

完成流程图.png

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 )
  • 无法原生监听数组, 需要特殊处理

Proxy的使用.png

开课吧

7

vue为什么要求组件模版只能有-个根元素

从三方面考虑:

  1. new Vue({el:' #app'})

2.单文件组件中,template下的元素div。其实就是"树”状数据结构中的"根"。

一个vue单文件组件就是一个vue实例, 如果template下有多个div那么如何指定vue实例的根入口呢,为了让组件可以正常生成一个vue实例, 这个div会自然的处理成程序的入口,通过这个根节点,来递归遍历整个vue树下的所有节点,并处理为Ndom,最后再渲染成真正的HTML,插入在正确的位置。

  1. df算法要求的,源码中,patch.js里patchVnode()。