Vue3学习记录(一)
vue3项目创建
可以使用Vite快速创建vue3项目
安装:npm install -g create-vite-app
创建项目:create-vite-app projectName
Vue2和Vue3的比较
diff比较
Vue2的diff是全局比较

Vue3的diff是谁有标记就比较谁

vue3新增了静态标记(PatchFlag),每次比较的时候只会比较带有patch flag的节点,并且通过pacth flag的类型得知要比较的内容。
// pacth flag 值与类型的对应关系
export const enum PatchFlags {
TEXT = 1,// 动态文本节点
CLASS = 1 << 1, // 2 // 动态 class
STYLE = 1 << 2, // 4 // 动态 style
PROPS = 1 << 3, // 8 // 动态属性,但不包含类名和样式
FULL_PROPS = 1 << 4, // 16 // 具有动态 key 属性,当 key 改变时,需要进行完整的 diff 比较。
HYDRATE_EVENTS = 1 << 5, // 32 // 带有监听事件的节点
STABLE_FRAGMENT = 1 << 6, // 64 // 一个不会改变子节点顺序的 fragment
KEYED_FRAGMENT = 1 << 7, // 128 // 带有 key 属性的 fragment 或部分子字节有 key
UNKEYED_FRAGMENT = 1 << 8, // 256 // 子节点没有 key 的 fragment
NEED_PATCH = 1 << 9, // 512 // 一个节点只会进行非 props 比较
DYNAMIC_SLOTS = 1 << 10, // 1024 // 动态 slot
HOISTED = -1, // 静态节点
// 指示在 diff 过程应该要退出优化模式
BAIL = -2
}
静态提升
Vue2中无论元素是否参与更新,每次都会重新创建,然后再次渲染。
Vue3中对于不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用即可。
const _hoisted_1 = /*#__PURE__*/_createElementVNode("a", null, "哎哟喂 ", -1 /* HOISTED */)
const _hoisted_2 = /*#__PURE__*/_createElementVNode("p", null, "静态文本", -1 /* HOISTED */)
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock("div", null, [
_hoisted_1,
_hoisted_2,
_createElementVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
]))
}
事件侦听器缓存
默认情况下(不使用cacheHandlers)onClick会被视为动态绑定,所以每次都会去追踪它的变化。
但是因为是同一个函数,所以没有追踪变化,直接缓存起来复用即可。
事件监听缓存
开启事件监听缓存之前:
const _hoisted_1 = ["onClick"]
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock("div", null, [
_createElementVNode("button", { onClick: _ctx.Pooo }, "按钮", 8 /* PROPS */, _hoisted_1)
]))
}
开启事件监听缓存之后:
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock("div", null, [
_createElementVNode("button", {
onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.Pooo && _ctx.Pooo(...args)))
}, "按钮")
]))
}
渲染和挂载
计算器:{{count}}
组合API
vue3提出了组合式API,并且提出了可以使用组合式API的地方——setup.
{{count}}
setup
setup函数执行时机位于beforeCreate和created之前,所以setup函数中是无法使用data和methods,并且由于此时尚未创建组件实例,所以setup中并没有this。
setup函数只能是同步的不能是异步的。
async setup(){} ×
reactive
reactive是vue3中提供的实现响应式数据的方法。在Vue2中响应式数据是通过defineProperty实现的。
Object.defineProperty(obj,'要监听的属性名',{set(newVal){},get(){}})
缺点:①不能监听数组的变化
? ②必须遍历对象的每个属性
? ③必须遍历深层次的对象
在Vue3中响应式数据是通过es6中的proxy对象实现的
let proxy = new Proxy(obj,handler)
优点:
①无需一层层递归为每个属性添加代理
②可以完美监听到任何方式的数据改变
reactive参数必须是对象(json/arr)
如果给reactive传递了其他对象:
-
默认情况下修改对象,界面不会自动更新
-
如果想更新,可以通过重新赋值的方式
let state = reactive({
time:new Date()
})
function myFn(){
//state.time.setDate(state.time.getDate()+1) 数据变了,视图没有变
const newtime = new Date(state.time.getTime())
newtime.setDate(state.time.getDate()+1)
state.time = newtime
}
ref
ref适合对简单类型数据的监听。ref低层的本质还是reactive,系统会自动转换成ref(xx)=>reactive({value:xx})
注意点:
①在Vue中使用ref的值不需要通过value获取
②在js中使用ref的值需要通过value获取
setup(){
let count = ref(123); // 这里会转为{value: 123}
function handleClick(){
count.value++;
console.log(count.value); // 124
}
return { count, handleClick }
}
vue是如何判断当前的数据是否是ref类型的,通过当前数据的__v_isRef私有属性来判断的,Vue3提供了isRef和isReactive判断类型。