前置知识:Vue3.0带来的变化
- 使用monorepo的形式来管理源代码
- Vue2.0使用flow进行类型检测,Vue3.0源码使用Typescript来进行重写
- 性能方面:Vue2.0使用Object.defineProperty来劫持,无法监听给对象添加/删除的属性.Vue3.0使用Proxy进行数据劫持,
- 由Options API到Composition API,数据管理更加清晰
- 通过hooks实现代码的共用性,Vue2.0使用mixin来共享代码
初次体验Vue3.0
引入Vue3.0
- CDN(通过互联网共享网络,使用最靠近每个用户的服务器)引入
- CDN服务器:阿里,腾讯,亚马逊,Google等
- 开源服务器:unpkg,JSDelivr,cdnjs
<script src="https://unpkg.com/vue@next"></script>
- 下载Vue的文件,手动导入
- NPM下载安装
- Vue Cli自动导入
<script src="https://unpkg.com/vue@next"></script>
<script>
let tempObj = {
template: `<h2>Hello World~</h2>`,
}
const App = Vue.createApp(tempObj)
App.mount('#app');
</script>
使用Vue和原生JavaScript对比实现一个计数器
查看Vue3.0源码
- 查看方式github搜索
vue-next - tags选择v3.2.0版本, git clone到本地
- 安装本地依赖,
yarn install, 本地运行yarn run dev - package.json的「dev」开启
--sourcemap,方便直接定位到相对应的源代码文件 - 通过debugger的形式查看源码
Composition API
setup传递2个参数,props和context:
- props 为父组件的数据传值
- context 执行上下文
- attrs
- slot
- emit
import {ref} from "vue";
setup(){
const counter = ref(10); //counter的ref的引用值,Vue可以实现自动解包的过程.页面可以直接绑定counter的引用值
const increment = ()=>{
counter.value++;
}
return {
counter,
increment
}
}
////////////////////////////
import {reactive} from "vue";
setup(){
const counter = reactive({count:10});
const increment = ()=>{
counter.count++;
}
return {
counter,
increment
}
}
实现Vue3.x中的数据响应式数据如果是复杂数据使用reactive,如果复杂变量传入简单变量的话系统会报警告,reactive直接修改对象里面的属性,简单变量是用ref是作为响应式的引用维护着它内部的值,简单变量修改.value属性修改具体内部的值。
readonly会返回原生对象的只读代理,proxy会对set方法进行数据劫持.
自定义Ref
<template>
<div>
<h1 ref="titleDOM"></h1> //获取原生DOM
</div>
</template>
//定义hooks
import { customRef } from "vue";
export default function (value, delay=300) { //默认为300ms,可以设置时间,自定义hooks第二个参数即可
let timer = null;
return customRef((track, trigger) => {
return {
get() {
track();
return value;
},
set(newValue) {
clearTimeout(timer);
timer = setTimeout(() => {
value = newValue;
trigger();
}, delay);
},
};
});
}
//引入代码
<template>
<div>
<input type="text" v-model="inputValue" /> <br />
{{ inputValue }}
</div>
</template>
<script>
import debounce from "./hooks/useDebounce";
export default {
props: {
message: {
type: String,
required: true,
},
},
setup() {
let titleDOM = ref(null); //默认绑定title的DOM
const inputValue = debounce();
return {
inputValue,
titleDOM
};
},
};
</script>
computed
computed默认是一个ref对象,需要修改其内部.value的值
let firstName = ref('hello');
let lastName = ref('hello');
let fullName = computed(()=>{}
return firstName.value+lastName.value;
)
watch / watchEffect 监听数据变化
watchEffect会自动监听数据变化,会默认执行一次作为自动执行的依赖。
//当年龄大于25时,停止watchEffect的监听
const stopAddAge = watchEffect((onInvalidate) => {
onInvalidata(()=>{
console.log("清除副作用...");
})
console.log("年龄:", age.value);
});
function handleAgeAdd() {
age.value++;
if (age.value > 25) {
stopAddAge();
}
}
watch相比较于watchEffect是懒执行的
let info = reactive({name:"huangfl"})
//监听reactive对象的某一个属性值时,reactive监听变化需要进行转换
watch(()=>info.name, (newValue, oldValue)=>{
console.log(newValue, oldValue);
})
//监听整个reactive对象
watch( info, (nv, ov)=>{
console.log(nv, ov);
})
watch监听多个数据源
//适用于监听reactive类型的数据
watch([name, info],([oldName, newName], [oldInfo, newInfo])=>{
console.log(oldName, newName, oldInfo, newInfo);
})