Vue3.x学习纪录

1. Vue2到Vue3

vue3项目搭建

  • 1.安装vue3的cli
    cnpm i -g @vue/cli@nextjavascript

    @next 是由于没有正式发布,后面正式发布可能会去掉html

    2.建立vue3项目
    vue create <name>vue

    3.vue3项目java


    vue3跟vue2差很少 多了一个composition APIreact

    vue3和ts的配合更好了npm

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注入到一个组件当中 json

​ 2.重用组件的代码---vue2.x种组件里面东西特别多、特别乱(data、method、computed、...)数组


​ composition API——注入
​ 把东西(数据、方法、computed、生存周期函数、...)注入到组件当中——集中到一个地方写app


//普通方式
export default {
  data(){ a: 12 },
  methods: {
    fn(){
      ....
    }
  },
  computed: {}
}
//composition API
export 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 }),只是会自动加value
        console.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
    // 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原始数据

  1. toRaw

    若是数据有大量的操做,一直被监听可能会影响性能,能够先把数据转换成原始数据,改完以后再变回去

    //reactive、ref、readonly -> 原始数据
    let json = reactive({ ... }; //proxy
    let obj = toRow(json);  // {...}
    //原始数据 ->  reactive、ref、readonly
    reactive(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);
    
    //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
    跟原始数据无关(至关于复制) 会引用原始数据(改的话都会变)
    会触发页面渲染 不会触发页面渲染
  3. 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')}
  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(...);
    }
相关文章
相关标签/搜索