vue

基础知识

原理

Vue2.0/3.0 双向数据绑定原理

各自的好处,到掘金上面寻找一些文章。

Vue2.0 使用 ES5 方法:defineProperty

数据劫持

Object.defineProperty(obj, 'key', { get() {}, set() {}, });

Vue3.0 使用 ES6 方法:Proxy

let obj = {};

obj = new Proxy(obj, { get(target, prop) {}, set(target, prop, value) {} });

vue-router

vuex

单元测试

服务器渲染

组件库

  1. vdom
  2. 模板渲染

组件化 响应式 vdom 和 diff 模板编译 渲染过程 前端路由

重点:整体流程是否全面,热门技术是否有深度。

关于 vue 的一些问题

  1. v-for 为什么要使用 key? 答:diff 算法通过 tag 和 key,来判断是否是相同的 node。目的是为了减少渲染次数,提高渲染性能。

组件化

引入一个组件,传入相关信息。

如何理解 MVVM 模型?

数据驱动视图。 只需要修改数据,框架就会根据数据的变化更新视图。

M = Modul V = View VM = ViewModul

View <=> ViewModul <=> Modul

Vue3.0 - Proxy

3.0:使用 Proxy 实现数据响应式。

2.0:使用 defineProperty 实现数据响应式。

Object.defineProperty 的缺点

  1. 深度监听需要一次性递归,有性能瓶颈。
  2. 无法监听新增属性和删除属性,需要使用 Vue.set 等方法。
  3. 无法原生监听数组,需要特殊处理。

Proxy 基本使用

new Proxy(data, {
    get(target, key, receiver) {
        const result = Reflect.get(target, key, receiver);
        return result;
    },
    set(target, key, val, receiver) {
        const result = Reflect.set(target, key, val, receiver);
        return result;
    },
    deleteProperty(target, key) {
        const result = Reflect.deleteProperty(target, key);
        return result;
    }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14

虚拟 DOM(Virtual DOM)

问:什么是 vdom? 答:vdom 是真实 DOM 的一种映射。使用 JS 模拟出来的一种 DOM 结构。

问:vdom 有什么用? 目的是为了提高性能。DOM 操作本身非常耗费性能,JS 本身运行却很快,为了减少复杂度,减少性能消耗,所以使用 JS 模拟 DOM 结构,先计算出最小变更,再操作 DOM。

用 JS 模拟 DOM 结构

<div id="root">
    <h1 class="title">title name</h1>
    <ul class="list">
        <li class="list-item">item</li>
    </ul>
</div>
1
2
3
4
5
6
const vdom = {
    tag: 'div',
    props: {
        id: 'root'
    },
    children: [
        {
            tag: 'h1',
            props: {
                className: 'title',
            },
            children: 'title name'
        },
        {
            tag: 'ul',
            props: {
                className: 'list'
            },
            children: [
                {
                    tag: 'li',
                    props: {
                        className: 'list-item'
                    },
                    children: 'item'
                }
            ]
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

diff 算法

问:什么是 diff 算法? 答:diff 算法是 JS 对虚拟 DOM 对比的过程。

问:diff 算法有什么用? 答:通过这个算法,计算对比出 vdom 的最小变更。

问:diff 的比较规则是什么? 答: 1.只比较同一级别,不跨级比较。 2.同一级中 tag 不相同,则直接删除重建,不深度比较。 3.同一级中 tag 和 key,两者都相同,则认为是相同节点,不深度比较。

key 的作用

vue3

搭建项目

必备插件

  • Vue3 + script setup + ts + Vite + Volar
  • CSS 预处理器: sass
  • PostCSS: autoprefixer、postcss-pxtorem
  • amfe-flexible

目录结构

响应性 API

响应性基础 APIopen in new window

  • reactive
  • ref
  • toRef
  • toRefs
  • shallowRef

reactive

返回对象的响应式副本。将解包所有深层的 refs,同时维持 ref 的响应性。

ref

接受一个内部值并返回一个响应式且可变的 ref 对象,里面仅有一个 .value property,指向该内部值。

toRef

可以用来为源响应式对象上的某个 property 新创建一个 ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。 当你要将 propref 传递给复合函数时,toRef 很有用。

toRefs

将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref

shallowRef

创建一个跟踪自身 .value 变化的 ref 但不会使其值也变成响应式的。

用法

ref通常用来处理简单的基本类型数据,返回一个响应式 Ref 对象。reactive用来定义更加复杂的数据类型,但是定义后里面的变量取出来就不再是响应式 Ref 对象,所以需要使用toRefs转化为响应式 Ref 对象。

如果只修改引用类型的一个属性,推荐用reactive;如果需要给变量重新赋值,推荐使用ref

  • toRef 将传入的 props 其中一个属性转成响应式
  • toRefs 将传入的 props 所有属性转成响应式

组合式 API

  • setup
  • 生命周期钩子
  • Provide / Inject

把同一功能的代码放到一起维护,也可以抽离到一个组建中。

teleport

v-model

小技巧

列表渲染

你可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:

<div v-for="item of items"></div>
1

还可以用第三个参数作为索引:

<li v-for="(value, name, index) in myObject">
  {{ index }}. {{ name }}: {{ value }}
</li>
1
2
3

key

使用 key 强制替换元素或组件,而不是重复使用它,达到一些特别的目的。

比如:

  • 完整地触发组件的生命周期钩子
  • 触发过渡
<transition>
  <span :key="text">{{ text }}</span>
</transition>
1
2
3

text 发生改变时,<span> 总是会被替换而不是被修改,因此会触发过渡。

ref

ref 为我们的值创建了一个响应式引用。在整个组合式 API 中会经常使用引用的概念。

import { ref } from 'vue'

const counter = ref(0)

console.log(counter) // { value: 0 }
console.log(counter.value) // 0

counter.value++
console.log(counter.value) // 1
1
2
3
4
5
6
7
8
9

Provide / Inject

Proxy

Vue Class Component

Vue Class Componentopen in new window

使用技巧

defineComponent

可以创建一个自定义组件。

可以创建一个只有在需要时才会加载的异步组件。

import { defineComponent } from 'vue'
export default defineComponent({
  props: {},
  created() {
    console.log('defineComponent')
  },
  setup() {
    return {}
  },
})
1
2
3
4
5
6
7
8
9
10

setup 中使用 emit

setup(props, context) {
  function handle() {
    context.emit('change', 123)
  }
}
1
2
3
4
5
Last Updated: 2023/1/28 16:25:34
Contributors: 黎聪, licong96