Remember a vue3.0 technology sharing meeting

Posted May 22, 202012 min read

Remember a vue3.0 technology sharing meeting

Recorded the technical sharing meeting within the group, students with the same needs can refer to
The sharing time is about 1 hour

1. Version

It is still in the beta version, and it will take some time to be officially used in the project, but the structure and APIs should not change much.

The list here is not complete, but it is enough
1. Alpha closed beta version
2. Beta beta version
3. Candidate version officially released by Gamma
4. Final official version
5. Plus enhanced version
6. full version
7. Trial trial version(generally limited in time or function)

2. Introduction

  1. Learn a new technology, just like practicing the new hero of the glory of the king. Exploring his fun can bring joy to the developer. Using new good technology will make the work more enjoyable.

  2. This version of vue is similar to "My World", all of which are composed of blocks. Don't underestimate the blocks. If there are more blocks, they can even form a circle(quantity changes cause qualitative changes). Fresh play can only stimulate our interest.

Three. Vue3.0 environment construction

Prepare a set up environment to prevent accidents when the time comes, and then follow the steps to build a version on the spot.
  1. npm install -g @vue/cli cli upgrade to version 4

  2. Create a random project, vue create next-test

  3. It is better to choose the router and vuex to choose the configuration, which is convenient for subsequent upgrade

  4. The command provided by vue add vue-next cli to evolve to the next version, after execution, it will automatically upgrade the router and vuex to the alpha version.

Four. Vue3.0 important optimization

  1. The speed of template compilation is improved, and the processing of static data is skipped.
  2. Monitor the array
  3. Have a good support for ts
  4. Fully compatible with version 2.x
  5. There can be multiple root nodes(also bugs, such as display:flex on the outer layer, then the inside will be affected, which means that the layout is more flexible but also more careful, in short, please be responsible for your own code and others)
  6. Support Source map, although there is no demo, but this is really important

V. Changes to the initial writing of vuex, router, vue

vue:
import {createApp} from'vue';
import App from'./App.vue'
import router from'./router'
import store from'./store'

//Method one. Creating an instance becomes a chain, writing it down directly feels that the semantics and structure are a bit vague, but we have to understand the good intentions of vue to do this, and the front end tends to be functional.
//createApp(App).use(router).use(store).mount('#app')

//Method Two.
const app = createApp(App);
app.use(router);
app.use(store);
app.mount('#app');
vuex:
import {createStore} from'vuex'
//A method dedicated to creating instances
export default createStore({
  state:{
  },
  mutations:{
  },
  actions:{
  },
  modules:{
  }
});
router
import {createRouter, createWebHistory} from'vue-router';
import Home from'../views/Home.vue'

const routes = [
  {
    path:'/',
    name:'Home',
    component:Home
  }

]

const router = createRouter({
//Function to create history
  history:createWebHistory(process.env.BASE_URL),
  routes
})

export default router

VI. Definition of Variables

1:ref

import {ref} from "vue";
export default {
  //1:The basic logic of this version is completed in the setup, some people say that he is regarded as 2.x data.
  setup() {
    //2:Define a tracking variable, that is, two-way binding.
    const n = ref(1); //The generated n is an object, which is convenient for vue to monitor it
    function addN() {
      n.value++; //Note that you need to use the form of .value, because n is the object  , value is his value
    }
    return {
      n, //Only return the template of the page to use it, {{n}} is not needed.
      addN
    }
  }
 }

2:reactive

import {reactive, toRefs} from "vue";
export default {
  setup() {
    //Note:reactive objects cannot be returned or imported as a structure, it will cause the loss of responsive
    const obj = reactive({
      name:"Golden Retriever",
      age:4
    });
    function addObj() {
      obj.age++;
    }
    return {
      ...obj, //If you write badly, you will lose responsiveness
      obj, //If you write it like this, you should call it based on obj, type {{obj.age}}
      ...toRefs(obj) //Must be an object generated by reactive, ordinary objects are not allowed, he took out each item and wrapped it, we can use {{age}} like this, rest assured how deep our obj Can also respond
    }
  }
 }

7. Where does the previous ref go

This dude was robbed of keywords by others, so he can only change his own way
  <div>
    <div ref="content">The first step, defined on the dom, he will have a callback</div>
  </div>
  <ul>
    <li>ref from v-for</li>
    <li>It can be written as an expression, and it can be deduced how vue is implemented</li>
    <li>v-for does not need to be so troublesome when using vue2.x, it will be assembled into an array if written directly
    <li :ref="el => {items[index]= el }" v-for="(item,index) in 6" :key="item">{{item}}</li>
  </ul>

import {ref, onMounted, onBeforeUpdate} from "vue";

export default {
  setup() {
    //2:Define a variable to receive dom, the name does not matter, but if it is unified with dom, it will be very semantic.
    const content = ref(null);
    const items = ref([]);

    //4:In the life cycle, this value has been changed, so of course I got it the first time
    onMounted(() => {
      console.log(content.value);
      console.log("li tag group", items.value);
    });

    //5:Make sure to reset the reference before every change
    onBeforeUpdate(() => {
      items.value = [];
    });

    //3:The returned name must be the same as the ref of the dom, so that you can receive the callback of the dom
    return {
      content,
      items
    };
  }
};

8. Life cycle

<template>
  <div>
    <button @click="add">Click to increase, trigger updata</button>
    <p>{{obj.count}}</p>
  </div>
  <p>
    2.x vs. 3.0
    beforeCreate -> use setup()
    created -> use setup()
    beforeMount -> onBeforeMount
    mounted -> onMounted
    beforeUpdate -> onBeforeUpdate
    updated -> onUpdated
    beforeDestroy -> onBeforeUnmount
    destroyed -> onUnmounted
    errorCaptured -> onErrorCaptured
  </p>
</template>

<script>

//These lifecycle registration methods can only be used in the setup hook
import {onMounted, onUpdated, onBeforeUnmount, reactive} from "vue";
export default {
  //1:The setup looks lengthy, you can do some plugins to optimize it yourself
  //2:More clear intention in itself
  //3:Need to establish the correct code awareness of engineers
  //4:Insufficient ability may write worse code
  //The author says:The gain of raising the upper bound is far greater than the loss of lower bound. It is worth pondering, the front end needs to raise the threshold
  //5:When to call:Create a component instance, then initialize props, and then call the setup function. From the perspective of the lifecycle hook, it will be called before the beforeCreate hook
  //6:These lifecycle hook registration functions can only be used synchronously during setup(), because they rely on the internal global state to locate the current component instance(the component instance that is calling setup()), and do not call these under the current component The function throws an error.
  //7:In principle, no specific logic will be placed in the life cycle, even if there is only one sentence assigned a ternary, it can not be placed, which is also in line with the current engineering mode

  //Discussion:How many ways can I determine which function a function is currently in?
  //For example, whether there are multiple layers of nested components
  setup() {
    onMounted(() => {
      console.log("is mounted!");
    });
    onUpdated(() => {
      console.log("is onUpdated!");
    });
    onBeforeUnmount(() => {
      console.log("is onBeforeUnmount!");
    });
    const obj = reactive({
      count:1
    });
    function add() {
      obj.count++;
    }
    return {
      obj,
      add
    };
  }
};
</script>

9. Routing

<template>
  <div>
    {{id}}
  </div>
</template>

<script>
import {getCurrentInstance, ref} from'vue';
export default {
  setup(){
    const {ctx} = getCurrentInstance()
    //1. This is also to remove this
    //2. Convenient type deduction
    console.log(ctx.$router); //push and other methods
    console.log(ctx.$router.currentRoute.value); //routing example
    //This is actually not necessary to become ref because this value is not necessary to be dynamic
    //But he is too long, this is really unbearable
    const id = ref(ctx.$router.currentRoute.value.query.id)

    //4:page blocker
    ctx.$router.beforeEach((to, from,next)=>{
      console.log('Routing life cycle')
      next()
    })
    return {
      id
    }
  }
}

</script>

10. vuex

import {createStore} from'vuex'

//Does the front-end trend only have functions?
export default createStore({
  state:{
    name:'Night, you got me',
    age:24,
    a:'White',
    b:'black'
  },
  mutations:{
    updateName(state, n){
      state.name += n
    }
  },
  actions:{
    deferName(store) {
     setTimeout(()=>{
       //Only commit can modify the value, I am against this setting, can discuss
       //The structure of vuex itself is very procrastination, and I don't like the use of domain
      store.state.name ='Awesome, you changed it back'
     },1000)
    }
  },
  getters:{
    fullName(state){ return `${state.a}-+ -${state.b}`}
  },
  modules:{
  }
});

<template>
  <div>
    <p>{{name}}</p>
    <button @click="updateName('+')">Click to change the name</button>
    <br />
    <button @click="deferName('+')">Change back</button>

    <p>{{fullName}}</p>
  </div>
</template>

<script>
import {useStore} from "vuex";
import {computed} from "vue";
export default {
  setup() {
    const store = useStore();
    //1:single introduction
    const name = computed(() => store.state.name);
    //2:Introduce the entire state
    const state = computed(() => store.state);
    console.log("Instance of vuex", state.value); //don't forget.value

    //3:The method is actually taken directly from the body
    const updateName = newName => store.commit("updateName", newName);

    //4:action means
    const deferName =() => store.dispatch("deferName");

    //5:The getter has not changed
    const fullName = computed(() => store.getters.fullName);
    return {
      name,
      fullName,
      deferName,
      updateName,
    };
  }
};
</script>

11. composition(this is probably the most important reform)

The front end is function-oriented programming, and various specifications are also approaching function
The composition makes the front-end engineer's programming specification closer to the native js, 30 years from Hedong to 30 years from Hexi, a few years ago the frontend needed templates to'regulate', now the frontend wants more free.
If you are developing a project instead of a plug-in, don't use mixin anymore. This thing can't be traced back to the source. The semantics are so bad that we have to say'no' to it.
The variable name of the example is a bit low, sorry~~
<template>
  <div>
    <button @click="addN1">Add above</button>---> {{n1}}
  </div>
   <div>
    <button @click="addN2">Add below</button>---> {{n2}}
    <button @click="addN210">n2+10 each time</button>
  </div>
  <div>
    <p>This can also be referenced in the component, which can replace some of the functions of the mixin</p>
    <button @click="addN3">Increase in n3</button>---> {{n3.value}}
  </div>
  <div>
    <com></com>
  </div>
</template>

<script>
import {ref} from'vue';
import n3Change from'./mixin';
import com from'../components/composition.vue';

export default {
  components:{
    com
  },
  setup(){
     //1:setup is just an integration function
     //2:Even the entire function may not have specific logic
     //3:According to this inference, the variables defined by ref and other methods will automatically identify which setup is inside, so as to achieve logical reuse
     //4:This method can be a good substitute for mixin
     //5:Of course, data can also be intercepted here to do some things
     const {n2, addN2} = n2Change();
     function addN210(){
       n2.value += 10
     }
     return {
       ...n1Change(),
       ...n3Change(),
       n2,
       addN2,
       addN210
     }
  }
}
//It can even be written anywhere, the responsive freedom is greatly improved
function n1Change(){
   const n1 = ref(1);
   let addN1 =()=>{
     n1.value++
   }
   return {
     n1,
     addN1
   }
}

function n2Change(){
   const n2 = ref(1);
   let addN2 =()=>{
     n2.value++
   }
   return {
     n2,
     addN2
   }
}
</script>

Write it anywhere, then import it to become a mixin

import {reactive} from'vue';


export default()=> {
  const n3 = reactive({
    name:'mixin',
    value:1
  })
  const addN3=()=>{
    n3.value++
  }
  return {
    n3,
    addN3
  }
}

12. New ideas for plugins

//The development plugin does not have to be mounted on the vue prototype
//Causes bloated vue prototypes, naming conflicts, etc.(for example, both ui are called message)
//The principle is provide and inject, dependency injection.

import {provide, inject} from'vue';

//The use of symbol here will not cause conflicts in variable names, and it is really reasonable architecture design to give the naming rights to users
const StoreSymbol = Symbol()

export function provideString(store){
  provide(StoreSymbol, store)
}

export function useString() {

  const store = inject(StoreSymbol)

  return store
}

Uniform initialization of the app.vue page

export default {
  setup(){
    //Some initialization'configuration/operation' can be done here
    //It needs to be placed in the corresponding root node, because it depends on provide and inject
     provideString({
       a:'Maybe I am axios',
       b:'Maybe I am a message box'
     })
  }
}

Receive in the component you need to use

<template>
  <div>
    Demo of the plugin
  </div>
</template>

<script>
import {useString} from'../plugin';

export default {
  setup(){
    const store = useString();
    //Not only get the value, you can define what can be obtained by the app
    console.log('Get the value', store)
  }
}

</script>

13. New observer

<template>
  <div>
    <button @click="addn1">n1 increase--{{n1}}</button>
    <button @click="addn2">n2 increase--{{n2}}</button>
    <button @click="addn3">n3 increase--{{n3}}</button>
  </div>
</template>

<script>
import {watch, ref} from "vue";
export default {
  setup() {
    const n1 = ref(1);
    const n2 = ref(1);
    const n3 = ref(1);
    //1:monitor one
    //The first parameter is the function return value, of course, you can also write n1 directly
    //If you are listening to an attribute in an object, you need to write this function, which is much smarter than the 2.x string.

    watch(
     () => n1.value,
     (val, oldVal) => {
        console.log("New value", val);
        console.log("Old value", oldVal);
      }
   );
    //2:monitor multiple
    //There are multiple definitions in the form of an array, which is a problem. If the object I observe is an array, and each item is a function that returns a value, wouldn't he be mistaken for a multi-monitor structure distressed
    watch(
      [() => n2.value,()=>n3.value],
     ([val, val3],[val2, val4]) => {
        //val is the new value of n2 val2 is the old value of n2
        //val3 is the new value of n3 val4 is the old value of n3
        console.log("The correspondence between the new value and the old value", val, val2);
        console.log("The correspondence between the new value and the old value", val3, val4);
      }
   );

    function addn1() {
      n1.value++;
    }
    function addn2() {
      n2.value++;
    }
     function addn3() {
      n3.value++;
    }
    return {
      addn1,
      addn2,
      addn3,
      n1,
      n2,
      n3
    };
  }
};
</script>

13. New calculation properties

Don't watch watchEffect with a'watch', but his function can be classified as a calculated attribute
<template>
  <div>
    <button @click="addCount">Click calculation</button>
    <button @click="setCount(1)">Click to start set</button>
    <p>count--{{count}}</p>
    <p>count2--{{count2}}</p>
    <p>count3--{{count3}}</p>
  </div>
</template>

<script>
//Made it similar to react
import {computed, ref, watchEffect} from "vue";
export default {
  setup() {
    const count = ref(1);
    //1. The default definition
    const count2 = computed(() => count.value * 2);
    console.log(count2.value); //also value because it may be a simple type
    //2. Of course getter and setter can be defined
    const count3 = computed({
      get:() => count.value * 3,
      set:val => {
        //reset count here
        count.value = val;
      }
    });
    //3. watchEffect is more like a calculation function
    //Immediately execute a function passed in, and track its dependencies responsively, and rerun the function when its dependencies change
    //The listener will be linked to the life cycle of the component and will automatically stop when the component is uninstalled.
    //Vue's responsive system caches the side-effect function and refreshes it asynchronously, such as changing count and conut4 at the same time watchEffect is only executed once
    //The initialization operation is executed before the component is mounted. Therefore, if you want to access the DOM(or template ref) when writing side-effect functions, please do it in the onMounted hook
    //Not the return value, but monitoring all the values   in it. Any changes will be re-executed, he should be able to play something.
    const count4 = ref(1);
    const stop = watchEffect(() => {
      if(count4.value) {
        console.log("As a judgment condition can also be re-executed according to the change of count4");
      }
      console.log(count.value);
    });
    setTimeout(() => {
      stop(); //stop listening
    }, 10000);
    function addCount() {
      count.value++;
      setTimeout(() => {
        count4.value++;
      }, 1000);
    }
    //trigger setter
    function setCount() {
      count3.value = 2;
    }
    return {
      count,
      count2,
      addCount,
      count3,
      setCount
    };
  }
};
</script>

14. customRef anti-shake

Of course, "anti-shake" is not the point here, the point is this kind of code thinking
<template>
  <div>
    <input type="text" v-model="text" />
  </div>
</template>

<script>
import {customRef, onUnmounted} from "vue";
export default {
  setup() {
    let timeout = null; //does not need to be responsive
    const text = useDebouncedRef("hello",(time) => {
      //After all, it is delayed, don't worry about getting this value
      console.log("Delayed execution callback", text.value);
      console.log('Time instance', time)
      timeout = time;
    });
    //Good habits are also necessary to become a qualified engineer
    onUnmounted(()=>{
        clearTimeout(timeout);
    })
    return {
      text
    };
  }
};

//Not written in pure js, you can use customRef to monitor this value every move
//The wording is average, but there is one more idea, thanks
function useDebouncedRef(value, callback, delay = 200) {
  let timeout;
  //The two parameters are track for tracking and trigger for triggering the response
  //The tracking of values   by these two parameters is currently not useful, such as the starting mechanism of watchEffect
  //It is no problem not to call these two values, but if you write it as a plugin, you still have to call it, because others may not be tracking this value,

  //Note:This function cannot have a large delay. If it exceeds 500, you need to consider the clear timer when the component is destroyed, but the logic is deepened. At this time, we can get the instance of the demo every time.
  return customRef((track,trigger) => {
    return {
      get() {
        track()
        return value;
      },
      set(newValue) {
        clearTimeout(timeout);
        //callback received too late, you can use another function or object here to receive
        timeout = setTimeout(() => {
          value = newValue;
          trigger()
          callback(timeout);
        }, delay);
      }
    };
  });
}
</script>

15. Components and injection

Father

<template>
  <div>
    Components:
    <zj :type="type" @ok="wancheng"></zj>
  </div>
</template>

<script>
import zj from "../components/subcomponent.vue";
import {ref} from'vue';
import {provide} from'vue'

export default {
  components:{
    zj
  },
  setup() {
    provide('name','pass down value'); //basic value
    provide('name2', ref('pass down value')); //monitoring value
    const type = ref('Most');

    function wancheng(msg){
      console.log('Subcomponent-->', msg)
      setTimeout(()=>{
        type.value ='xxxxxxx'
      },2000)
    }
    return {
      type,
      wancheng
    }
  }
};
</script>

Subassembly

<template>
  <div>The property of props does not need to be set to return --- {{type}}</div>
</template>

<script>
import {inject, ref} from'vue'
//In order for TypeScript to deduce the type correctly, we must use createComponent to define the component:
export default {
  props:{
    type:String
  },
  //1:Props cannot be deconstructed, they will lose responsiveness
  //2:context is the context, we can get methods such as slots emit
  //3:The separation of props and context is also for clearer type deduction of ts
  //setup({type}){
  setup(props, context) {
    //1:props
    console.log("props", props.type);
    console.log("Context", context);
    context.emit('ok','delivery completed')

    //2:injection
    console.log('inject',inject('name'));
    console.log('inject', inject('xxxx','I am the default'))
    inject('name1', ref('default value')) //The receiver can also do this
  }
};
</script>

16. Summary

Every time I see a new technology, it feels fun. The unchanging life will be too boring. In some ways, vue loses some of its original advantages, but people can be compatible with vue2.x. The time of the manuscript is almost an hour. It is best to hand-tap every point on the spot. It will be fascinating to show everyone the code that has been written. The thing I dislike the most when I study the video is that the teacher said "I will not demonstrate this ""
So much this time, I hope to make progress with you.