历史
- 2015年 10月27 1.0.0 Evangelion 新福音战士
- 2016年 10月1日 2.0.0 Ghost in the Shell 攻壳机动队
- 2019年 2月 2.6
- 2020年 9月18日 3.0.0 One Piece(海贼王)
- 2021年 8月10日 3.2.0
vue3 的优势
- 更快快(初次渲染,更新渲染)
- 小 (打包大小, 内存占用)
- 响应式Proxy 和relfect
- 重写了 虚拟DOM实现 diff Tree-shaking
- 拥抱**TS **
MVC MVVM
- MVC(model 从数据库取数据 controller 逻辑代码 View 视图) c 把 m 展示 成 v
- MVVM vm把v的改变反应到m, 同时把m的数据渲染到v
指令
- v-once: 只渲染一次
- v-slot 缩写是# 默认插槽 #=‘data’
- v-pre 跳过编译
- v-cloak
组件间通信
简单的层级比如: 父子 孙子
1. props/$emit
2. 获取实例: $parent $children($children vue3.0移除了) $refs(vue3用ref, 同时子组件需要defineExpose暴露数据)
3. $attrs和$listener(vue3被移除了) 这两个属性有点类似,一个得到的是没在props定义的属性, 一个得到的是自定义方法, 可以直接传方法, 这样子组件调用父组件的方法, 可以父子组件传值
4. provie inject
复杂的层级
5. Vuex/pinia
6. eventBus(vue3被移除了$on $emit $once,但可以借助第三方工具来完成。Vue 官方推荐使用 mitt 或 tiny-emitter) 事件总线.利用了vue实例的$emit $on
7. 使用浏览器本地缓存,例如localStorage, 他是没有响应式的.
绑定样式
动态class对象:<div :class="{ 'is-active': true, 'red': isRed }"></div>
动态class数组:<div :class="['is-active', isRed ? 'red' : '' ]"></div>
动态style对象:<div :style="{ color: textColor, fontSize: '18px' }"></div>
动态style数组:<div :style="[{ color: textColor, fontSize: '18px' }, { fontWeight: '300' }]"></div>
响应式
整体思路是数据代理和数据劫持+观察者模式(发布订阅者模式)
对象内部通过 defineReactive 方法,使用 Object.defineProperty 将属性进行劫持(只会劫持已经存在的属性),数组则是通过重写数组方法来实现。当页面使用对应属性时,每个属性都拥有自己的dep属性,存放他所依赖的 watcher(依赖收集),当属性变化后会通知自己对应的 watcher 去更新(派发更新)。
- 数据代理: 通过一个对象代理对另一个对象属性的操作(读写)
- 为什么vm能直接获取data的数据, 就是用Object.defineProperty() 做了数据代理(计算属性的原理) _data 就是data
怎么让数据丢失响应式
vue3简单, 不做响应式处理即可(ref reactive toRef)
// 方法一:将数据定义在data之外
data () {
this.list1 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }
return {}
}
// 方法二:Object.freeze()
data () {
return {
list1: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}),
}
}
对象新属性无法更新视图:使用Vue.$set(obj, key, value),组件中this.$set(obj, key, value)
删除属性无法更新视图:使用Vue.$delete(obj, key),组件中this.$delete(obj, key)
vue2=>vue3的变化
- vscode安装valor 卸载 vetur
vue 不在限制单根节点了,非单根节点需要指定绑在哪个节点上v-bind="$attrs", 单根节点就默认绑定在了根节点上, 子节点再绑定$attrs依然生效
<my-component class="a"></my-component>
template directives 模板指令
1. v-model替代 .sync修饰符, 当然还是要emit('update:modelValue',123)
2. key值的用法改变,v-if/v-else/..不需要绑定key了,template使用v-for的key值可以放template上了
3. v-if 和 v-for的优先级 vue3变为v-if优先级更高, 不过没什么意义, 通常不一起使用.
4. v-bind的合并策略有变化,
Global API Application Instance
Slots Unification 插槽合一
一些小变动
在这里插入代码片
ref reactive
处理基本数据原理是 Object.defineProperty get set
处理对象数据: reactive 函数(底层是 proxy)
let name = ref('miller'), // 生成一个引用对象
obj = ref({ // 实际还是用了reactive
type: 1,
salary: 20
})
reactive({})
reactive([1, 2, 3]) // 数组也可以用, 可以直接通过索引改了.
vue2的对象和数组的响应式的问题, 比如对象添加一个属性, 要用$set, 数组的话,要用改变原数组的方法才能监测到(当然重新赋值没问题)
vue3因为用到了proxy就没有了这个问题, 对象添加属性或者数组直接通过下标修改数据, 都是响应式的.
toRef 和 toRefs
let person = reactive({
name: "miller",
age: 12,
});
let personName = toRef(person, "name");
// personName是响应式数据, 且和 person里的name 做了关联
return {
...toRefs(person) // 这样模板里面就不用一直写 person. person.
}
readonly shallowReadonly
- 让一个响应式数据变为只读的(深只读)
- 让一个响应式数据变为只读(浅只读 只有第一层只读)
let person = reactive({
name: 'yogaMiller',
job: {
salary: "20",
},
});
person = readonly(person);
toRaw markRaw
- 将一个由 reactive 定义的响应式数据转为普通对象
- markRaw 标记一个对象, 让其永远不会变成响应式.(提升性能)
customRef 自定义ref
import { customRef } from 'vue'
xxx(value) {
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(v) {
value = v
trigger()
}
}
})
}
02. 模板语法
- v-bind={} :=“” 绑定多个属性
import { ref, reactive, nextTick } from 'vue'
const a = ref(0) // 通常用来处理基本数据类型,如果处理对象,本质还是用的reactive
a.value // 模板上使用不能.value,但要注意为顶层属性
let obj = { name: ref('zml') } // obj.name 就是非顶层属性
// 响应式对象内的嵌套对象依然是代理
const proxy = reactive({})
const raw = {}
proxy.nested = raw
console.log(proxy.nested === raw) // false
04.计算属性
const c = computed(() => {
return ...
})
比如想排序过滤啥的, 不想改变原数据,可以用计算属性
c.value // 模板使用不需要
计算属性 | 方法 |
---|---|
使用上 不能加( ) | 方法要加(事件绑定的方法可不加) |
计算属性可以设置setter getter | |
只用getter的时候可以简写 |
05.绑定class和style
const classObject = computed(() => ({
active: isActive.value && !error.value,
'text-danger': error.value && error.value.type === 'fatal'
}))
06.条件渲染
- v-if v-else-if v-else v-show
07.列表渲染 v-for
- v-for和v-if 都可搭配template v-show不行
const todos = ref([
{ id: 1, name: 'zml' },
{ id: 2, name: '猪八戒' }
])
能用三目就用三目, 别总 if
const filteredTodos = computed(() => {
return hideCompleted.value
? todos.value.filter((t) => !t.done)
: todos.value
})
setup 语法糖
<script setup>
const props = defineProps({
msg: String
})
// 声明触发的事件
const emit = defineEmits(['response'])
// 带参数触发 经常搭配click
emit('response', 'hello from child')
</script>
<slot>Fallback content</slot>
watch
let todo = ref(1)
// 傻了, 动不动就就写回调
watch(todo, () => {
fetchData()
})
// fetchData本来就是个函数
watch(todo, fetchData)
- 可以监听$route
- arr.length
- 监听对象里面的: obj.name
- computed
- 可以监听props??
watch: { // vue2
a(a) {
handler(a) { // handler 不能变的
},
deep: true // 深度监视, 来监听对象里面的所有属性.
immediate: true; 一上来就执行一次
}
}
watch(a, () => {}, { immediate: true }) // 监听的是ref 定义的(基本, 对象)
watch(() => obj.a, (v) => {}) //
watchEffect(() => {
// 这里面用到了谁, 这个方法就重新调用....挺像computed, 但不用写返回值.
})
- 监视reactive定义的响应式数据时, 强制开启了深度监视(deep配置失效), oldValue无法正确获取
- 监视reactive定义的响应式数据的某个属性时, deep配置生效
watch([a, b, c], () => {}) // 监视多个ref定义的响应式数据
watch(person.job, (n, o) => {}, { deep: true, immediate: true }) // 监视reactive定义的数据的某个属性
vue3的核心是setup
1. setup(组合式api,相对于vue2的选项式)
- setup的执行时机是,在beforeCreate之前的, this是undefined, 所以不用this
- props(组件内部需要声明接收) 和 context 两个参数, contex(attrs - 没有声明接收的props slots emit)
<script>
export default{
setup() { // 不能用async修饰; setup 和 data 不要混用 同名会覆盖data的数据
let a = ref(0) // 这里返回的数据可以直接使用,
return { a }
return () => h('h1', 'csdn') // 也可以返回渲染函数 (不常用)
}
}
</script>
理解: hook 类似mixin, 哪里不同?
vue.config.js lintOnSave: false; 关闭语法检查
1. v-for 配合 ref (不兼容)
用处: 性能优化
- 原来会直接变成ref数组, 现在因为效率问题, 需要自己绑定个函数, 然后可以把refs放数组或者对象里面
2. v-for 和v-if 优先级问题(不兼容)
用处: 性能优化
- 2.X版本是 v-for 优先级高, 现在变成了v-if的优先级更高, 也更符合自然理解
还是不要放在同一个标签里使用, 先用计算属性筛选下数据.
3. 异步组件 defineAsyncComponent(新增)
用处: 性能优化 核心模块通过框架加载, 非核心模块通过服务器异步加载???
联想: 区别于路由懒加载
const asyncModal = () => import('./Modal.vue') // 返回Promise?
应该是让自己在组件里返回promise
纯函数: 一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数.
RT,即real time(实时) Regression Testing(回归测试)。 也有Reaction Time(响应时间)的意思。
逻辑单元?
4. attribute false 不会移除属性了
5. $attr 包含了 style和class了
关注点分离是架构设计的重要原则之一.
“系统中的一个部分发生了变化,不会影响其他部分。”
“即使需要改变,也能够清晰地识别出那些部分需要改变。”
“如果需要扩展架构,将影响最小化,已经可以工作的每个部分都将继续工作。
如果能够将同一个逻辑关注点相关代码收集在一起会更好。而这正是组合式 API 使我们能够做到的。
- setup能用this? 为啥?
不能, 因为是在实例化之前, 找不到组件实例) - setup() 执行时机? (beforeCreate)之前
- setup()的两个参数? (props也需声明接收, context) context(attrs, slots, emit)
- 搭配suspense 异步引入组件(defineAsyncComponent) promise 实现异步(延迟加载组件)re
- vue2的方法读取vue3的setup中的数据和方法,反过来不行。
- 不能用 async修饰。
- 判断 isRef() isReactive() isReadonly() isProxy()
<Suspense>
<template #default>
<Asy msg="Hello Vue 3.0 + Vite" />
</template>
<template #fallback> 等一等 </template>
</Suspense>
import { defineAsyncComponent } from 'vue'
const Asy = defineAsyncComponent(() => import('./components/asy.vue'))
setup() {
let sum = ref(0)
return new Promise((res) => {
setTimeout(() => {
res({ sum }) // 和data同名的话,这里的优先级更高。
}, 3000)
})
return () => h('h1', 'hello')
}
响应式
beforeCreate(数据监测,数据代理创建之前)
响应式: Vue 最独特的特性之一,是其非侵入性的响应性系统 (它举了个表格计算的例子)
ref(0) // ref 处理基本数据, 如果处理对象还是借助reactive
reactive({})
toRefs toRef 区别. customRef(官网) shallowReactive shallowRef
toRef是把对象中的某个属性变成响应式; toRef(person, 'name')
toRefs(obj)
toRaw 把reactive生成的响应式对象转换为普通对象
markRaw是让一个对象
永远不会成为响应式对象. 使用场景, 比如有些值不该是响应式的.(如第三方类库)
vue 2.x对象是用了defineProperty做数据劫持, 数组是重写更新数组的方法.
vue 3 Proxy 代理(拦截变化)和reflect 反射(操作对象)
$set
- this. s e t 要注意啥 , v u e 3 的变化不能设置根数据的响应式 , v u e 3 不用它了 . 也能设置数组 . 添加响应式数据要用 t h i s . set要注意啥, vue3的变化 不能设置根数据的响应式, vue3不用它了. 也能设置数组. 添加响应式数据要用 this. set要注意啥,vue3的变化不能设置根数据的响应式,vue3不用它了.也能设置数组.添加响应式数据要用this.set(o,‘a’,123)
- 对象替换, 对象的地址发生改变了. vue能监视到
- 为什么vm.a 能直接访问到data里面的数据
数据代理; Object.definePropery在vue实例对象的_data设置了代理, 代理了里面的data的数据
数据代理: 通过一个对象代理另一个对象中的属性操作.(读/写? 删除呢?) - v-model有什么修饰符
number type=“number” 配合(
lazy 失去焦点才更改
trim
其他变化
- 全局api 的转移 放app上了 let app = createApp() 工厂函数
Vue.config | app.config. |
---|---|
vm.componnet | app.component |
- | app.directive |
- | app.mixin |
- | app.use |
- | app.config.globalProperties |
双向绑定原理
- vue2 Object.defineProperty 做数据劫持(知道哪些数据变化了) 结合 发布订阅者模式, 让对应的节点知道
参考
vue3官网指南
vue官方互动教学
vue官方-sync修饰符
vue官方-迁移指南
「自我检验」熬夜总结50个Vue知识点,全都会你就是神!!!