Vue3安装
Vue-cli脚手架:npm install -g @vue/cli -----> vue create
Vite:npm install vite-app
Vue3新特性
Composition API、自定义Hooks、生命周期钩子、Teleport、Suspense(带插槽的组件)、Fragment(代码多个片段)、Tree-Shaking(nextTick)
Composition API
reactive、ref、toRefs、watch、watchEffect、computed、生命周期钩子 使用setup时,它接受两个参数: 1.props:组件传入的属性 2.context:attrs、slot 和emit
ref能处理 js 基本类型,也可以定义对象的双向绑定 reactive函数确实可以代理一个对象, 但是不能代理基本类型 toRefs用于将一个reactive对象转化为属性全部为 ref 对象的普通对象
watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。
watch(source, callback, [options])
- source: 可以支持 string,Object,Function,Array; 用于指定要侦听的响应式变量
- callback: 执行的回调函数
- options:支持 deep、immediate 和 flush 选项。
侦听 reactive、ref 定义的数据
import { defineComponent, ref, reactive, toRefs, watch } from "vue";
export default defineComponent({
setup() {
const state = reactive({
nickname: "xiaofan",
age: 20,
room: {
id: 100,
attrs: {
size: "140平方米",
type: "三室两厅",
},
}
});
const year = ref(0);
setTimeout(() => {
state.age++;
year++;
}, 1000);
// 修改age、year值时会触发 watch的回调
watch([() => state.age, year,() => state.room], ([curAge, newVal], [preAge, oldVal],[preAge1,oldVal2]) => {
console.log("新值:", curAge, "老值:", preAge);
console.log("新值:", newVal,"老值:", oldVal);
},{ deep: true });
return {
...toRefs(state),
};
},
});
watchEffect
import { defineComponent, ref, reactive, toRefs, watchEffect } from "vue";
export default defineComponent({
setup() {
const state = reactive({ nickname: "xiaofan", age: 20 });
let year = ref(0)
setInterval(() =>{
state.age++
year.value++
},1000)
watchEffect(() => {
console.log(state);
console.log(year);
}
);
return {
...toRefs(state)
}
},
});
- watchEffect 不需要手动传入依赖
- watchEffect 会先执行一次用来自动收集依赖
- watchEffect 无法获取到变化前的值, 只能获取变化后的值
Teleport
即希望继续在组件内部使用Dialog, 又希望渲染的 DOM 结构不嵌套在组件的 DOM 中。 此时就需要 Teleport 上场,我们可以用<Teleport>包裹Dialog, 此时就建立了一个传送门,可以将Dialog渲染的内容传送到任何指定的地方。
// index.html
<body>
<div id="app"></div>
<div id="dialog"></div>
</body>
// Dialog.vue
<template>
<teleport to="#dialog">
<div class="dialog">
<div class="dialog_wrapper">
<div class="dialog_header" v-if="title">
<slot name="header">
<span>{{ title }}</span>
</slot>
</div>
</div>
<div class="dialog_content">
<slot></slot>
</div>
<div class="dialog_footer">
<slot name="footer"></slot>
</div>
</div>
</teleport>
</template>
vue2与vue3
Object.defineProperty与Proxy
- Object.defineProperty只能劫持对象的属性, 而Proxy是直接代理对象 由于Object.defineProperty只能劫持对象属性,需要遍历对象的每一个属性,如果属性值也是对象,就需要递归进行深度遍历。但是Proxy直接代理对象, 不需要遍历操作
- Object.defineProperty对新增属性需要手动进行Observe 因为Object.definePropert劫持的是对象的属性,所以新增属性时,需要重新遍历对象, 对其新增属性再次使用Object.defineProperty进行劫持。也就是Vue2.x中给数组和对象新增属性时,需要使用set内部也是通过调用Object.defineProperty去处理的。