May 31, 2021 Article blog
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:
watch
is used in
Vue3.0
Vue3.0
uses calculated properties
Vue3.0
is used in
vue-router
3.0
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.
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
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.
$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
}
)
})
}
}
}
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
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 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 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)
}
}
$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)
}
}
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.
Vue2.0
computed: {
getName() {
const { firstName, lastName } = this.info
return firstName + lastName
}
},
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
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
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
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)
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
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
beforeCreate
and
created
When using
componsition api
setup
actually
beforeCreate
and
created
because
setup
is the actual entry function of the component.
beforeDestroy
and destroyed have
destroyed
their names
In
setup
beforeDestroy
is renamed
onBeforeUnmount
and
destroyed
is
onUnmounted
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.