共计 5370 个字符,预计需要花费 14 分钟才能阅读完成。
1. Vue2 到 Vue3
vue3 我的项目搭建
-
1. 装置 vue3 的 cli
cnpm i -g @vue/cli@next
@next 是因为没有正式公布,前面正式公布可能会去掉
2. 创立 vue3 我的项目
vue create <name>
3.vue3 我的项目
vue3 跟 vue2 差不多 多了一个
composition API
vue3 和 ts 的配合更好了
vue3 与 vue2 的区别
Vue3 与 Vue2 的不同:1.vue 实例化形式变了
//vue2
import Vue from 'vue';
import App from './App.vue';
new Vue({render: h => h(App)
}).mount('#app');
//vue3
import {createApp} from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
2.Vue 全局办法变了
//vue2
import Vue from 'vue';
Vue.component('name', {});
//vue3
import {createApp} from 'vue';
let app=createApp(App);
app.component('name', {});
app.mount('#app');
3.vue3 勾销了 filter 用 computed、函数代替
4.v-model
//vue2
v-model = :value + @input
//vue3
[html 组件]
v-model = :value + @input
[自定义组件]
v-model = :modelValue + @update:modelValue
5. 函数组件的写法变了
//vue2
render(h){return h(...);
}
//vue3
import {h} from 'vue';
render(props, context){return h(...);
}
6.data 变了
//vue 的 data 对立了,只有函数一种
data(){return {};
}
7. 异步组件(分包加载)//vue2
const cmp1=()=>import('./cmp1');
//vue3
import {defineAsyncComponent} from 'vue';
const cmp1=defineAsyncComponent(()=>import('./cmp1'));
8.vue3 事件简化了
//vue2
this.$emit('name', ...);
this.$on();
this.$off();
this.$once();
//vue3
this.$emit('name', ...);
9. 其余
自定义 directive 变了——beforeMount、mounted、beforeUpdate、updated、...
template 不须要根元素
2. 详解 composition API
composition API 到底是什么
1. 数据、办法、computed 注入到一个组件当中
2. 重用组件的代码 —vue2.x 种组件外面货色特地多、特地乱(data、method、computed、…)
composition API——注入
把货色(数据、办法、computed、生存周期函数、…)注入到组件当中——集中到一个中央写
// 一般形式
export default {data(){a: 12},
methods: {fn(){....}
},
computed: {}}
//composition API
export default {setup(){
return {
a: 12,
fn(){...},
}
}
}
setup、可响应数据—reactive
- setup
beforeCreate
setup
created
setup 执行程序是在
beforeCreate
之后created
之前,这个时候组件刚刚被 new 进去,组件外面什么也没有,所以无奈应用this
及其他的货色setup 无奈应用组件的其余货色(data、methods、computed、…)、也不要应用 this
setup 执行的过程中,组件中其余货色都没有创立;不能用 this
setup 是同步的(不能用 async) -
可响应数据
一般的变量,无奈实现响应操作(检测到数据变动,从新渲染组件)应用可响应数据(reactive)
import {reactive} from "vue"; const state = reactive({ xxx:xxx, xxx:xxx })
reactive
的参数必须是一个 objectreactive(number|string|boolean) ×
reactive({...}|[...]) √
必须是对象(json、数组)如果是其余对象(Date、RegExp、…),批改不会被监听(proxy 的起因),如果非要应用能够创立一个新的来笼罩。例如:
<template> <div>a={{a.date}}</div> <button type="button" @click="fn">++</button> </template> <script> import {reactive} from "vue"; export default {setup() {const a = reactive({ date: new Date() }); return { a, fn() { // 这样批改数据扭转页面不会刷新 // a.date.setDate(a.date.getDate() + 1); // 须要间接笼罩 const newDate = new Date(a.date.getTime() + 86400000); a.date = newDate; console.log(a.date); }, }; }, }; </script>
ref、readonly
-
ref
-
应用根本类型
-
应用
isRef
判断一个值是不是 refimport {ref, isRef} from "vue"; let a = ref(12); // 根本等价于 reactive({value: 12}),只是会主动加 value console.log(isRef(a)); //true - 判断是否 ref
在
template
中 ref 会主动加.value
,例如应用 a<template>{{a}}</template>
在 js 中须要本人加
.value
例如本人批改<script>fn(){ a.value++}</script>
-
-
援用节点(html 原生、自定义组件)
<template> <div ref="a">dsfasdfdas</div> </template> <script> import {ref, onMounted} from "vue"; export default {setup() {const a = ref(null); // 须要在 onMounted 中应用,不然在 setup 执行过程中 a 是不存在 onMounted(() => {a.value.style.border = "1px solid black";}); return {a,}; }, }; </script>
-
-
readonly
相似于
const
,不同的是:readonly
爱护所有操作、递归爱护;const
—- 仅爱护赋值、非递归isReadonly
判断一个值是不是 readonly<template> {{a.count}} <button type="button" @click="a.count++">++</button> </template> <script> import {readonly, isReadonly} from "vue"; export default {setup() {const a = readonly({ count: 12}); // a.count++ 的时候 const 会报正告,readonly 是递归爱护多层 // 判断一个值是不是 readonly console.log(isReadonly(a)); //true // const a = {count: 5}; // a.count++ 的时候 const 会减少,const 只爱护赋值操作,只爱护一层 return {a}; }, }; </script>
递归监听、shallow、trigger
- 递归监听(深度监听)
在 vue2.x 中批改对象属性页面是无奈实现刷新的,例如
this.data.obj.a = 12
页面并不会刷新(须要应用$set
),vue3.x 中实现了递归监听,批改data.obj.a = 12
页面也会刷新 -
shallow
&trigger
vue3 递归监听的实现原理是把多层数据全副改为
Proxy
,例如:import {reactive, shallowRef, triggerRef} from "vue"; // reactive、ref、readonly 都是递归监听,这里应用 ref 举例 // 非递归版本 // shallowReactive // shallowRef // shallowReadonly export default {setup(){ const json = reactive({arr:[ { a:12} ] }); console.log(json); // Proxy console.log(json.arr); // Proxy console.log(json.arr[0]); // Proxy return {json} } }
当数据特地宏大时,例如几万、几十万条数据时,性能可能会有影响(一般对象转成 proxy), 这个须要应用非递归版本,例如:
import {shallowRef, triggerRef} from "vue"; export default {setup(){ const json = shallowRef({arr: [ { a:12} ] }) console.log(json); // Proxy console.log(json.arr); // [...] console.log(json.arr[0]); // {...} setTimeout(()=>{json.value.arr[0].a++; console.log(json.value.arr[0].a); // 如果没有这一行,数据变,页面不会刷新 triggerRef(json); // 告诉页面刷新 }, 500) return {json} } }
raw 原始数据
-
toRaw
如果数据有大量的操作,始终被监听可能会影响性能,能够先把数据转换成原始数据,改完之后再变回去
//reactive、ref、readonly -> 原始数据 let json = reactive({...}; //proxy let obj = toRow(json); // {...} // 原始数据 -> reactive、ref、readonly reactive(obj); //proxy
把创立 reactive、ref 的参数返回来 对原始数据进行操作,不会被监听的(性能高)
-
markRaw 放弃一个数据永远是原始的
可能写库的时候会用,数据不会被转成 proxy,比方返回一个数据,不心愿这个数据被监听
let json = markRaw({xxx:xxx}); reactive(json); // object 不会被转成 proxy
深刻 ref 操作
- unRef 或如 ref 的原始数据
例如
let res = ref(12);
应用 toRaw 获取 => {value:12}
应用 unRef 获取 => 12
toRaw
是连着 value 一块获取的,unRef 是 ref 专用的 -
toRef
const json = {a:12}; let res = ref(json.a); res.value = 13; // 这个时候 res 的 value 会变为 13,然而 json 的内容不会变,相当于 ref 和原始数据没有关系,// let res = ref(json.a) 等价于 let res = ref(12); //toRef let res = toRef(json, "a"); res.value = 13; // 这个时候 res 的 value 和 json 的 a 都会变为 13,然而页面不会刷新 // ref - 一般 ref 对象 // 1. 不会跟原始数据挂钩 // 2. 会触发页面渲染 // toRef - 非凡的 ref 对象 // 1. 创立的 ref 对象,跟原始数据对象挂钩 // 2. 不会触发渲染
ref toRef 跟原始数据无关(相当于复制) 会援用原始数据(改的话都会变) 会触发页面渲染 不会触发页面渲染 -
toRefs
相当于 toRef 的批量操作
const json = {a:12, b:5} // toRef let res1 = toRef(json, "a"); let res2 = toRef(json, "b"); // toRefs let res = toRefs(json) // 相当于://toRefs({a: xx, b: xxx}) => {a: toRef(json, 'a'), b: toRef(json, 'b')}
-
customRef – 自定义 ref
function myRef(...){ //code... return customRef((track, trigger)=>{ // track == 整个 ref 开始 // trigger == 流程完结,告诉 vue 渲染 return {get(){track(); return xxxx; }, set(newVal){ // code.. trigger();} } }) } setup(){ // 返回的内容就是一般的 ref 对象 let data = myRef(...); }