基于vite创建vue3 ,2种方式对比
-
npm create vite@lates
自行配置 定制化选项
创建之后的目录:
-
npm init vite-app vue3-vite
需要快速开始一个Vue 3项目,不关心其他配置创建之后的目录:
-
包名称不同:
npm init vite-app vue3-vite 需要全局安装 @vitejs/create-app。
npm create vite@latest 需要全局安装 @vitejs/create-vite。
API
1. reactive
只适用于对象 (包括数组和内置类型,如 Map 和 Set,它不支持如 string、number 或 boolean 这样的原始类型)
import { reactive } from 'vue'
const counter = reactive({
count: 0
})
console.log(counter.count) // 0
counter.count++
注意:不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,必须始终保持对响应式对象的相同引用。不能轻易地“替换”响应式对象,因为这样的话与第一个引用的响应性连接将丢失:
js
let state = reactive({ count: 0 })
// 上面的 ({ count: 0 }) 引用将不再被追踪
// (响应性连接已丢失!)
state = reactive({ count: 1 })
对解构操作不友好:当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接:
js
const state = reactive({ count: 0 })
// 当解构时,count 已经与 state.count 断开连接
let { count } = state
// 不会影响原始的 state
count++
// 该函数接收到的是一个普通的数字
// 并且无法追踪 state.count 的变化
// 我们必须传入整个对象以保持响应性
callSomeFunction(state.count)
解构时也会失去响应式,可以使用toRefs
去转成响应式
2. toRefs
将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref
。每个单独的 ref 都是使用 toRef()
创建的。
消费者组件可以解构/展开返回的对象而不会失去响应性
const state = reactive({
foo: 1,
bar: 2
})
return {
...toRefs(state)
}
注意:toRefs
在调用时只会为源对象上可以枚举的属性创建 ref
。如果要为可能还不存在的属性创建 ref,请改用 toRef
。
3. ref()
则可以接受任何值类型。ref 会返回一个包裹对象,并在 .value 属性下暴露内部值
import { ref } from 'vue'
const message = ref('Hello World!')
console.log(message.value) // "Hello World!"
message.value = 'Changed'
4. computed
(具有缓存)
- 接受一个
getter
函数,返回一个只读的响应式 ref 对象
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
- 也可以接受一个带有 get 和 set 函数的对象来创建一个可写的 ref 对象
const count = ref(1)
const plusOne = computed({
get: () => count.value + 1,
set: (val) => {
count.value = val - 1
}
})
plusOne.value = 1
console.log(count.value) // 0
5. 路由独享守卫 beforeEnter
{
path: '/',
name: 'Home',
component: Home,
beforeEnter: (to, form, next) => { // 路由独享守卫
console.log(to, '路由独享守卫');
next()
}
},
6. 得到路由信息 vue3/vue2 区别
vue3
import { useRouter, useRoute } from 'vue-router'
export default {
setup() {
let router = useRouter(); // router是全局路由实例,是VueRouter实例
let route = useRoute(); // route对象表示当前的路由信息,包含了当前URL解析得到的信息,还有URL匹配到的路由记录
console.log(router, route, 'router')
router.push('/home') //路由跳转
}
}
vue2
this.$route.params
this.$router.push({
path: '/home'
params: {id: 1}
})
this.$route.query
this.$router.push({
path: '/home'
query: {id: 1}
})
7. ref()
获取dom
<template>
<div class="home">
<input type="text" ref="input">
</div>
</template>
import { ref } from "vue";
const input = ref();
console.log(input, 'input')
8. setup
中无法获取this 是undefined,所有生命周期之前调用
应用
- 如果想让对象变为响应式数据,使用erf 或 reactive
- 如果想让一个对象的所有属性只读,使用readonly
- 如果想要一个非对象数据变为响应式数据,使用ref
- 如果想要根据已知的响应式数据得到一个新的响应式数据, 使用computed
vue3 的效率提升
1. 静态节点会被提升
- 元素节点,没有动态绑定内容 会将节点从render函数提到外面,在vue2中 节点都写在render函数内部
2. 静态属性会被提升
3. 预字符串化
- 当编译器遇到大量连续静态内容,会直接将其编译为一个普通字符串节点,只有动态节点需要记录
- 在vue2中,会把每个元素变成一个虚拟节点
4. 缓存事件处理函数
- 会判断缓存中有没有这个函数,有的话直接返回,没有的话直接给函数赋值,保证事件函数只处理一次
5. Block Tree
- vue2在对比新旧树的时候,并不知道哪些节点是静态的,哪些节点是动态的,只能一层一层比较,浪费大部分时间在对比静态节点上
- vue3 会记录动态节点 在根节点,直接对比块 block,循环数组
6. PatchFlag
patchFlag是在编译template模板时,给vnode添加的一个标识信息,这个标识信息反映了vnode的哪些部位绑定了动态值,这样在runtime阶段,可以根据patchFlag判断出哪些内容需要更新,实现靶向更新
- vue2 会对比元素类型,属性, 子节点
- vue3 仅比较内容
- patchflag