Vue3.0 basic summary

Keywords: Front-end Vue Vue.js

Vue3.0 basic summary

2-year development, 99 contributors, 2600 submissions, 628 pr, 41% reduction in packaging volume, 55% faster initial rendering, 133% faster update, and 54% reduction in memory usage

Deficiencies of Vue2.x

  • Global API is easy to pollute the global environment

  • Mixin disadvantages: naming conflict, unclear variable source, reuse to components

  • Responsive:

    • Dynamic addition of root level responsive properties is not allowed

    • Object: the addition and removal of object properties cannot be detected. Vue.set(object,propertyName,value) can be used

    • Array: 1. You cannot directly set an array item by using the index. 2. You cannot modify the length of the array

      // It can be solved through Vue.set and splice()
      Vue.set(vm.items, indexOfItem, newValue);
      // Array.prototype.splice
      vm.items.splice(indexOfItem, 1, newValue);
      vm.$set(vm.items, indexOfItem, newValue);
      vm.items.splice(newLength);
      
      // Responsive principle
      Object.defineProperty(data, "count", {
        get() {},
        set() {},
      });
      new Proxy(data, {
        get(key) {},
        set(key, value) {},
      });
      

Vue3 common API s

  • setup(): execute props after being parsed before the component is created. It is the portal to the composite API.

    • The component instance was not created when setup was executed. Therefore, you can only access the following properties: props, attrs, slots and emit. You cannot access the following component options: data, computed, methods and refs (template ref)

    • To type infer the parameters passed to setup(), you need to use defineComponent.

      import axios from "axios";
      import { defineComponent } from "vue";
      export default defineComponent({
        async setup() {
          const res = await axios.get("url");
          return {
            data: res.data,
          };
        },
      });
      
    • Parameters:

      • Props: because props is responsive, you can't use ES6 to deconstruct. It will eliminate the responsiveness of props. If you need to deconstruct prop, you can use toRefs in the setup function

        import { toRefs } from 'vue'
        setup(props) {
          const { title } = toRefs(props)
          console.log(title.value)
        }
        
        //If title is an optional prop, there may be no title in props. toRefs will not create a ref for the title. You need to replace it with toRef
        import { toRef } from 'vue'
        setup(props) {
          const title = toRef(props, 'title')
          console.log(title.value)
        }
        
    • context: it is an ordinary JavaScript object, which is not responsive. You can safely use ES6 to deconstruct attrs, slots, emit and expose

      <!-- Get custom event -->
      <modal isOpen="ifOpen" @closeModel="closeIt">Elastic layer</modal>
      
      import { defineComponent } from "vue";
      export default defineComponent({
        setup(props, context) {
          const buttonClick = () => {
            // Name of emit dispatch event
            context.emit("closeModel");
          };
          return {
            buttonClick,
          };
      
          // context.attrs is the none props attribute
          // context.slots is equivalent to this.$slots in vue2.x
          // By h rendering, the value in the slot is rendered into the div element
          // return ()=>h('div',{},context.slots.default())
        },
      });
      
    • Combined API lifecycle hook

      • Beforecreate - > use setup()
      • Created - > use setup()
      • beforeMount -> onBeforeMount
      • mounted -> onMounted
      • beforeUpdate -> onBeforeUpdate
      • updated -> onUpdated
      • beforeUnmount -> onBeforeUnmount
      • unmounted -> onUnmounted
      • Rendertracked - > onrendertracked / / collect reactive dependencies again after each rendering
      • Rendertrigged - > onrendertrigged / / page re rendering is automatically executed every time it is triggered
      • activated -> onActivated
      • deactivated -> onDeactivated
      • errorCaptured -> onErrorCaptured
        setup(){
          const error = ref(null);
          errorCaptured(e){
            error.value = e
            return true
          }
        }
        
  • Reference of ref, reactive, toRefs, and toRef response expressions

    • Ref: change the value of the basic data type into a responsive value. The ref object has a single property.value that points to an internal value.

      const count = ref(0); // proxy({value:0})
      console.log(count.value); // 0
      count.value++;
      console.log(count.value); // 1
      
    • reactive: returns a responsive copy of the object

      setup(){
        const data = reactive({
          count: 0,
          increase: () => data.count++,
          double: computed(() => data.count * 2),
        });
        // toRefs converts proxy ({count: 0,...}) = > {count: proxy ({value, 0}),...} into a response expression that can be deconstructed
        const refData = toRefs(data);
        // reactive {Name: 'BJ'} = > proxy ({Name: 'BJ'}) response expression through proxy
        const obj = reactive({name:'bj'});
        // readOnlyObj can only read and cannot be modified. It can be passed to child components. Child components cannot modify parent components. One way data flow
        const readOnlyObj = readonly(obj)
        return {
          ...refData,
          obj
        };
      }
      
    • toRefs: it is a deconstructed responsive object and still has a responsive

      Convert a responsive object into a normal object, where each property of the result object is a ref pointing to the corresponding property of the original object. The returned object can be deconstructed / expanded without losing responsiveness

    • toRef: the response of the optional attribute of the object needs to use toRef. If there is no such attribute, this attribute will be added to the object, and the attribute value is empty. If there is no such attribute, toRefs will report an error

      setup(){
        // If you are not familiar with age in data, you will add a default data.age.value = ''
        const age = toRef(data, "age");
        setTimeout(() => {
          age.value = 18;
        }, 500);
        return { age };
      }
      
      
  • computed: calculated attribute

    const count = ref(1);
    const plusOne = computed(() => count.value + 1);
    console.log(plusOne.value); // 2
    plusOne.value++; // error
    
    // Accept an object with get and set functions to create a writable ref object
    const count = ref(1);
    const plusOne = computed({
      get: () => count.value + 1,
      set: (val) => {
        count.value = val - 1;
      },
    });
    plusOne.value = 1;
    console.log(count.value); // 0
    
  • watch,watchEffect

    [Vue warn]:Invalid watch source: watch source can only be a getter/effect function, a ref, a reactive object, or an array of these type

    • watch
      • lazy with certain inertia is not executed for the first time
      • Parameters can get the original value and current value
      • It can monitor the changes of multiple data
      watch([count, () => data.name], (newVal, oldVal) => {
        console.log(newVal, oldVal);
      });
      
    • watchEffect
      • Execute now, no lazy immediate
      • There is no need to transmit the listening content, and the code dependency is automatically perceived. There is only one callback function, which is triggered by the dependent code change
      • Cannot get the value of previous data
        const stop = watchEffect(() => {
          console.log(obj.name);
          setTimeout(() => {
            stop(); // Cancel watchEffect listening
          }, 500);
        });
        
  • Suspend asynchronous component

    <Suspense>
      <template #default>
        <async-show>
      </template>
      <template #fallback>
        <p>Loading...</p>
      </template>
    </Suspense>
    
  • Custom function hooks

    // Get mouse position
    import { ref, onMounted, onUnmounted } from "vue";
    const position = () => {
      const x = ref(0);
      const y = ref(0);
      const getPosition = (e) => {
        x.value = e.pageX;
        y.value = e.pageY;
      };
      onMounted(() => {
        document.addEventListener("click", getPosition);
      });
      onUnmounted(() => {
        document.removeEventListener("click", getPosition);
      });
    };
    export default position;
    
    // loading
    import { ref } from "vue";
    import axios from "axios";
    function reqLoading(url) {
      const res = ref(null);
      const loading = ref(true);
      const noLoading = ref(false);
      const error = ref(error);
      axios
        .get(url)
        .then((res) => {
          loading.value = false;
          noLoading.value = true;
          res.value = res.data;
        })
        .catch((e) => {
          loading.value = false;
          error.value = e.message;
        });
      return {
        res,
        loading,
        noLoading,
        error,
      };
    }
    export default reqLoading;
    
  • provide and inject

    • The inject function has two parameters:
      • name of property of inject
      • Default (optional)
    // Parent component
    setup() {
      const location = ref('North Pole')
      const geolocation = reactive({
        longitude: 90,
        latitude: 135
      })
      const updateLocation = () => {
        location.value = 'South Pole'
      }
      // readonly package, single data flow principle, and child components can only be modified through the method of parent components
      provide('location', readonly(location))
      provide('geolocation', readonly(geolocation))
      provide('updateLocation', updateLocation)
    }
    // Subcomponents
    setup() {
      const userLocation = inject('location', 'The Universe')
      const userGeolocation = inject('geolocation')
      const updateUserLocation = inject('updateLocation')
    
      return {
        userLocation,
        userGeolocation,
        updateUserLocation
      }
    }
    

Demo: todoList

// The properties and methods of the list are extracted
const listControl = () => {
  const { reactice } = Vue;
  const list = reactive([]);
  const addItem = (item) => {
    list.push(item);
  };
  return { list, addItem };
};
// The submitted properties and methods are extracted
const submit = () => {
  const { ref } = Vue;
  const inputValue = ref(null);
  const inputChange = (e) => {
    inputValue.value = e.target.value;
  };
  return { inputValue, inputChange };
};
const app = Vue.createApp({
  // The scheduler obtains the data to be returned
  setup() {
    const { list, addItem } = listControl();
    const { inputValue, inputChange } = submit();
    return {
      list,
      addItem,
      inputValue,
      inputChange,
    };
  },
  template: `
  <div>
    <div>
      <input :value="inputValue" @input="inputChange"/>
      <buttom @click="()=>addItem(inputValue)">Submit</buttom>
    </div>
    <ul>
      <li v-for = "(item,idx) in list" :key="idx">{{item}}</li>
    </ul>
  </div>
  `,
});

Posted by common on Fri, 29 Oct 2021 20:40:42 -0700