Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

What knowledge points have I gained with Vue 3.0 (II)


May 31, 2021 Article blog


Table of contents


The article comes from the public number: some play at the front end

I've been learning about Vue 3.0 lately outside of work, and although Vue3.0 is still rc, it doesn't stop us from learning. Today's article focuses on the following:

  1. watch is used in Vue3.0
  2. Vue3.0 uses calculated properties
  3. Vue3.0 is used in vue-router 3.0
  4. Vue3.0 uses vuex

watch is used in Vue3.0

watch is not a new concept in Vue3.0 and when using Vue2.x we often use watch to listen for changes in the results of an expression or function above the Vue instance.

Review the watch in Vue2.0

In Vue 2.0, we use watch to listen for changes in the expression or function calculations above Vue instance in a number of ways, as shown below

  1. The most common way to use it

   export default {
     data() {
       return {
         name: '子君',
         info: {
           gzh: '前端有的玩'
         }
       }
     },
     watch: {
       name(newValue, oldValue) {
         console.log(newValue, oldValue)
       },
       'info.gzh': {
         handler(newValue, oldValue) {
           console.log(newValue, oldValue)
         },
         // 配置immediate会在watch之后立即执行
         immediate: true
       }
     }
   }

We can configure the properties above the Vue instance to listen to in the watch property, or we can use . The key path to listen for changes to a property in an object can also be triggered by configuring immediate to listen immediately after listening, and deep to deeply listen to properties inside an object, regardless of how deep the nesting hierarchy is.

  1. Use $watch to listen

In addition to the regular watch object writing, Vue instance provides $watch method that allows you to monitor for changes to a property more flexibly by $watch F or example, in a scenario where we have a form, we want to be able to listen for data changes to the form after the user modifies it. B ut there is a special scenario where the form's backfilling data is requested asynchronously, when we want to listen for changes after the data has been requested in the background, at which point we can use $watch Here's what the code looks like:

   export default {
     methods: {
       loadData() {
         fetch().then(data => {
           this.formData = data
           this.$watch(
             'formData',
             () => {
               // formData数据发生变化后会进入此回调函数
             },
             {
               deep: true
             }
           )
         })
       }
     }
   }

  1. Listen for function expressions

In addition to listening to strings, the first argument $watch can also be a function that triggers a callback function when the return value of the function changes

   this.$watch(() => this.name, () => {
     // 函数的返回值发生变化,进入此回调函数
   })

Above, we use some of the common formulations of watch watch in Vue 2.0, for Vue3.0 because it is partially down-compatible with Vue 2.0, so the above usage is basically available in Vue3.0 but one of the highlights of Vue3.0 is the composition API so in addition to writing in Vue 2.0, you can also use componsition api

Use watch in Vue3.0

In Vue3.0 in addition to Vue 2.0, there are two api that can monitor data changes, the first is watch and the second is watchEffect For watch it is essentially the same as $watch usage in Vue 2.0, watchEffect is the new api provided by Vue3.0

The usage of the watch

The following example shows how to use watch

import { watch, ref, reactive } from 'vue'
export default {
  setup() {
    const name = ref('子君')
    const otherName = reactive({
      firstName: '王',
      lastName: '二狗'
    })
    watch(name, (newValue, oldValue) => {
      // 输出 前端有的玩 子君
      console.log(newValue, oldValue)
    })
    // watch 可以监听一个函数的返回值
    watch(
      () => {
        return otherName.firstName + otherName.lastName
      },
      value => {
        // 当otherName中的 firstName或者lastName发生变化时,都会进入这个函数
        console.log(`我叫${value}`)
      }
    )


    setTimeout(() => {
      name.value = '前端有的玩'
      otherName.firstName = '李'
    }, 3000)
  }
}

In addition to listening to a single value or a function return value, watch can also listen to multiple data sources at the same time, as shown in the following code:

export default {
  setup() {
    const name = ref('子君')
    const gzh = ref('前端有的玩')
    watch([name, gzh], ([name, gzh], [prevName, prevGzh]) => {
      console.log(prevName, name)
      console.log(prevGzh, gzh)
    })


    setTimeout(() => {
      name.value = '前端有的玩'
      gzh.value = '关注我,一起玩前端'
    }, 3000)
  }
}

The usage of watchEffect

The use of watchEffect is different from watch watchEffect passes in a function and executes it immediately, listens for responsive dependencies within the function, and then calls the incoming function again when the dependency changes, as shown in the following code:

import { ref, watchEffect } from 'vue'
export default {
  setup() {
    const id = ref('0')
    watchEffect(() => {
      // 先输出 0 然后两秒后输出 1
      console.log(id.value)
    })


    setTimeout(() => {
      id.value = '1'
    }, 2000)
  }
}

  1. Stop execution

$watch in Vue 2.0 returns a function at the time of the call, which can be executed to stop watch as shown in the following code

   const unwatch = this.$watch('name',() => {})
   // 两秒后停止监听
   setTimeout(()=> {
     unwatch()
   }, 2000)

In Vue3.0 watch like watchEffect also return a unwatch function that cancels execution, as shown in the following code

   export default {
     setup() {
       const id = ref('0')
       const unwatch = watchEffect(() => {
         // 仅仅输出0
         console.log(id.value)
       })

   
       setTimeout(() => {
         id.value = '1'
       }, 2000)
       // 1秒后取消watch,所以上面的代码只会输出0
       setTimeout(() => {
         unwatch()
       }, 1000)
     }
   }

  1. Remove side effects

Imagine a scenario where the interface has two drop-down boxes, the data for the second drop-down box is linked based on the data of the first drop-down box, and when the data for the first drop-down box changes, the data for the second drop-down box is obtained by sending a network request. That's when we can do this with watchEffect like the code below

      import { ref, watchEffect } from 'vue'


      function loadData(id) {
        return new Promise(resolve => {
          setTimeout(() => {
            resolve(
              new Array(10).fill(0).map(() => {
                return id.value + Math.random()
              })
            )
          }, 2000)
        })
      }


      export default {
        setup() {
          // 下拉框1 选中的数据
          const select1Id = ref(0)
          // 下拉框2的数据
          const select2List = ref([])
          watchEffect(() => {
            // 模拟请求
            loadData(select1Id).then(data => {
              select2List.value = data
              console.log(data)
            })
          })


          // 模拟数据发生变化
          setInterval(() => {
            select1Id.value = 1
          }, 3000)
        }
      }

Now if I switch the data for the first drop-down box, when the data request has been made, and then I switch this page to another page, because the request has already been made, so I hope that when the page leaves, I can end the request and prevent the data from returning an exception, and then I can use watchEffect to handle the situation for incoming arguments for the first callback function, as shown in the following code

      function loadData(id, cb) {
        return new Promise(resolve => {
          const timer = setTimeout(() => {
            resolve(
              new Array(10).fill(0).map(() => {
                return id.value + Math.random()
              })
            )
          }, 2000)
          cb(() => {
            clearTimeout(timer)
          })
        })
      }


      export default {
        setup() {
          // 下拉框1 选中的数据
          const select1Id = ref(0)
          // 下拉框2的数据
          const select2List = ref([])
          watchEffect(onInvalidate => {
            // 模拟请求
            let cancel = undefined
            // 第一个参数是一个回调函数,用于模拟取消请求,关于取消请求,可以了解axios的CancelToken
            loadData(select1Id, cb => {
              cancel = cb
            }).then(data => {
              select2List.value = data
              console.log(data)
            })
            onInvalidate(() => {
              cancel && cancel()
            })
          })
        }
      }

Vue3.0 uses calculated properties

Think about what we would normally do with calculated properties in Vue 2.0. I think the most common thing is that when there is a complex calculation in the template, you can use the calculation properties to calculate and then use them in the template, in fact, the calculation properties in Vue3.0 do the same thing as Vue 2.0.

  1. Use calculated properties in Vue2.0

     computed: {
       getName() {
         const { firstName, lastName } = this.info
         return firstName + lastName
       }
     },

  1. exist Vue3.0 Use the calculation properties in

   <template>
     <div class="about">
       <h1>{{ name }}</h1>
     </div>
   </template>
   <script>
   import { computed, reactive } from 'vue'


   export default {
     setup() {
       const info = reactive({
         firstName: '王',
         lastName: '二狗'
       })


       const name = computed(() => info.firstName + info.lastName)


       return {
         name
       }
     }
   }
   </script>

Like Vue 2.0, Vue3.0 calculated properties can also be set getter and setter such as the calculated properties in the code above, setting only getter i.e. adding cumputed is a function, then this is getter and if you want to set setter you need to write like this

   export default {
     setup() {
       const info = reactive({
         firstName: '王',
         lastName: '二狗'
       })

   
       const name = computed({
         get: () => info.firstName + '-' + info.lastName,
         set(val) {
           const names = val.split('-')
           info.firstName = names[0]
           info.lastName = names[1]
         }
       })

   
       return {
         name
       }
     }
   }

Vue3.0 is used in vue-router 3.0

Initialize vue-router

When we use vue-router in Vue 2.0, we implement a new VueRouter way, as in the following code VueRouter

import Vue from 'vue'
import VueRouter from 'vue-router'


Vue.use(VueRouter)
const router = new VueRouter({
  mode: 'history',
  routes: []
})
export default router

But by Vue3.0 the instance we created VueRouter had changed a little bit, just as Vue3.0 initializing Vue instance in main.js needed to be written as follows

import { createApp } from 'vue'
createApp(App).$mount('#app')

vue-router also modified to declare this function

import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
  // vue-router有hash和history两种路由模式,可以通过createWebHashHistory和createWebHistory来指定
  history: createWebHashHistory(),
  routes
})


router.beforeEach(() => {

  
})


router.afterEach(() => {

  
})
export default router

Then main.js pass

 createApp(App).use(router)

to refer to Vue

Use vue-router in setup

In Vue 2.0, we can get the current route through this.$route and then get the route instance through this.$router for routing jumps, but in setup we can't get this which means we can't use vue-router like Vue 2.0, and we need to use it like this

import { useRoute, useRouter} from 'vue-router'


export default {
  setup() {
    // 获取当前路由
    const route = useRoute()
    // 获取路由实例
    const router = useRouter()
    // 当当前路由发生变化时,调用回调函数
    watch(() => route, () => {
      // 回调函数
    }, {
      immediate: true,
      deep: true
    })

    
    // 路由跳转
    function getHome() {
      router.push({
        path: '/home'
      })
    }

    
    return {
      getHome()
    }
  }
}

Above, we use watch to monitor whether a route has changed, and in addition to watch we can also use the lifecycle functions provided by vue-router

import { onBeforeRouteUpdate, useRoute } from 'vue-router'
export default {
  setup() {
    onBeforeRouteUpdate(() => {
      // 当当前路由发生变化时,调用回调函数
    })
  }
}

In addition to onBeforeRouteUpdate vue-router also provides a lifecycle hook function when routing leaves

onBeforeRouteLeave(() => {
   console.log('当当前页面路由离开的时候调用')
})

Vue3.0 uses vuex

In fact, vuex is used in Vue3.0 in much the same way as vue-router

Initialize vuex

First create a new store/index.js and then add the following code

import { createStore } from 'vuex'


export default createStore({
  state: {},
  mutations: {},
  actions: {}
})

Then main.js in the following ways

 createApp(App).use(store)

Use vuex in setup

Like useRouter vuex provides useStore for use when calling, such as the following code

import router from '@/router'
import store from '@/store'
router.beforeEach(async (to, from, next) => {
  if (
    to.path !== '/login' &&
    store.getters['permission/getRoleMenus'].length === 0
  ) {
    await store.dispatch('permission/loadRoleMenus')
    next()
  } else {
    next()
  }
})

The rest of the usage is basically the same as the usage in Vue2.0 as you can refer to vuex official documentation

Life cycle hook function in Vue 3.0

As we said earlier, Vue3.0 is compatible with part Vue2.0, so the lifecycle hook function hasn't changed for Vue 2.0 component writing, but if you're using componsition api you need to make some adjustments

  1. Cancel beforeCreate and created

When using componsition api setup actually beforeCreate and created because setup is the actual entry function of the component.

  1. beforeDestroy and destroyed have destroyed their names

In setup beforeDestroy is renamed onBeforeUnmount and destroyed is onUnmounted

  1. Change the name of the lifecycle function to on+XXX for example, mounted onMounted updated onUpdated

How lifecycle functions are used in setup

setup() {
    onMounted(() => {
      console.log('mounted!')
    })
    onUpdated(() => {
      console.log('updated!')
    })
    onUnmounted(() => {
      console.log('unmounted!')
    })
  }

The actual usage is basically the same as Vue 2.0, but the writing has changed, so the cost of learning is very low.

Above is W3Cschool编程狮 about the use of Vue3.0, I gained what knowledge points (II) related to the introduction, I hope to help you.