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实例化形式变了//vue2import Vue from 'vue';import App from './App.vue';new Vue({  render: h => h(App)}).mount('#app');//vue3import { createApp } from 'vue';import App from './App.vue';createApp(App).mount('#app');2.Vue全局办法变了//vue2import Vue from 'vue';Vue.component('name', {});//vue3import {createApp} from 'vue';let app=createApp(App);app.component('name', {});app.mount('#app');3.vue3勾销了filter 用computed、函数代替4.v-model//vue2v-model = :value + @input//vue3[html组件]v-model = :value + @input[自定义组件]v-model = :modelValue + @update:modelValue5.函数组件的写法变了//vue2render(h){  return h(...);}//vue3import {h} from 'vue';render(props, context){  return h(...);}6.data变了//vue的data对立了,只有函数一种data(){  return {};}7.异步组件(分包加载)//vue2const cmp1=()=>import('./cmp1');//vue3import {defineAsyncComponent} from 'vue';const cmp1=defineAsyncComponent(()=>import('./cmp1'));8.vue3事件简化了//vue2this.$emit('name', ...);this.$on();this.$off();this.$once();//vue3this.$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 APIexport default {  setup(){    return {      a: 12,      fn(){        ...      },    }  }}

setup、可响应数据—reactive

  1. setup
    beforeCreate
    setup
    created

    setup执行程序是在beforeCreate之后created之前,这个时候组件刚刚被new进去,组件外面什么也没有,所以无奈应用this及其他的货色

    setup无奈应用组件的其余货色(data、methods、computed、...)、也不要应用this

    setup执行的过程中,组件中其余货色都没有创立;不能用this
    setup是同步的(不能用async)

  2. 可响应数据
    一般的变量,无奈实现响应操作(检测到数据变动,从新渲染组件)

    应用可响应数据(reactive)

    import { reactive } from "vue";const state = reactive({    xxx:xxx,    xxx:xxx})

    reactive的参数必须是一个object

    reactive(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

  1. ref

    1. 应用根本类型

      • 应用

        isRef判断一个值是不是ref

        import { ref, isRef } from "vue";let a = ref(12);  //根本等价于 reactive({ value: 12 }),只是会主动加valueconsole.log(isRef(a)); //true - 判断是否ref

        template中ref会主动加.value,例如应用a

        <template>{{a}}</template>

        在js中须要本人加.value 例如本人批改

        <script>fn(){ a.value++ }</script>

    2. 援用节点(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>
  2. 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

  1. 递归监听(深度监听)

    在vue2.x中批改对象属性页面是无奈实现刷新的,例如this.data.obj.a = 12页面并不会刷新(须要应用$set),vue3.x中实现了递归监听,批改data.obj.a = 12页面也会刷新

  2. shallow&trigger

    vue3递归监听的实现原理是把多层数据全副改为Proxy,例如:

    import { reactive, shallowRef, triggerRef } from "vue";// reactive、ref、readonly 都是递归监听,这里应用ref举例// 非递归版本// shallowReactive// shallowRef// shallowReadonlyexport 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原始数据

  1. toRaw

    如果数据有大量的操作,始终被监听可能会影响性能,能够先把数据转换成原始数据,改完之后再变回去

    //reactive、ref、readonly -> 原始数据let json = reactive({ ... }; //proxylet obj = toRow(json);  // {...}//原始数据 ->  reactive、ref、readonlyreactive(obj); //proxy

    把创立reactive、ref的参数返回来 对原始数据进行操作,不会被监听的(性能高)

  2. markRaw 放弃一个数据永远是原始的

    可能写库的时候会用,数据不会被转成proxy,比方返回一个数据,不心愿这个数据被监听

    let json = markRaw({xxx:xxx});reactive(json); // object 不会被转成proxy

深刻ref操作

  1. unRef 或如ref的原始数据

    例如let res = ref(12);

    应用toRaw获取 => { value:12 }

    应用unRef获取 => 12

    toRaw是连着value一块获取的,unRef是ref专用的

  2. 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);//toReflet res = toRef(json, "a");res.value = 13;// 这个时候res的value和json的a都会变为13,然而页面不会刷新// ref - 一般ref对象//    1. 不会跟原始数据挂钩//    2. 会触发页面渲染// toRef - 非凡的ref对象//    1. 创立的ref对象,跟原始数据对象挂钩//    2. 不会触发渲染
    reftoRef
    跟原始数据无关(相当于复制)会援用原始数据(改的话都会变)
    会触发页面渲染不会触发页面渲染
  3. toRefs

    相当于toRef的批量操作

    const json = { a:12, b:5 }// toReflet res1 = toRef(json, "a");let res2 = toRef(json, "b");// toRefslet res = toRefs(json)//相当于://toRefs({a: xx, b: xxx}) => {a: toRef(json, 'a'), b: toRef(json, 'b')}
  4. 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(...);}