10

Vue 3.0 上手(二)高级 API 及生命周期的上手

 3 years ago
source link: http://www.yukapril.com/2020/08/29/vue-3-2.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Vue 3.0 上手(二)高级 API 及生命周期的上手

上一次学习了基础的 API ,这次学习一些高级一点的 API。

Vue 初始化变化(上一篇章遗漏了)

原来的写法是:

1
2
3
4
5
6
7
8
9
// 创建实例及挂载插件
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')

// 全局挂载
Vue.prototype.$toast = msg => console.log(msg)

新的写法是:

1
2
3
4
5
6
// 创建实例,第二个可以配置全局参数
const app = createApp(App, { user: 'yukaPriL' })
// 挂载插件
app.use(router).use(store).mount('#app')
// 全局挂载
app.config.globalProperties.$toast = msg => console.log(msg)

main.js 一般都是项目生成出来,很少自己改,所以还好。

高级 API 用法

高级用法主要是更好的实现逻辑,是对基础 API 的封装和补充。

toRef / toRefs

之前文章提到过一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
setup () {
const state = reactive({
count: 0,
sum: computed(() => state.count * 9.99)
})

...

return {
// ...state <-- 错误,不能展开,否则会失去响应
// count: state.count <-- 错误,同样不可以返回数值型,也会失去响应
// 必须直接返回 state
state
}
}

直接返回时候,是不能进行对象展开的,展开后会导致失去响应。

但我们可以对返回内容进行包裹,再实现一次响应式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
setup () {
const state = reactive({
v1: 1,
v2: 2
})
const state2 = reactive({
v3: 3
})
setTimeout(() => {
state.v1++
state.v2++
state2.v3++
}, 2000)

return {
...toRefs(state),
v3: toRef(state2, 'v3')
}
}

通过使用 toRef toRefs,使得展开后的对象仍然具有响应性,不管我们后续再模板中使用,还是写 hooks 组件,都可以直接使用其值(而不是需要访问对象的属性):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 现在可以这样写: -->
<template>
<div>
<h1>ToRefs</h1>
<p>v1:{{ v1 }}</p>
<p>v2:{{ v2 }}</p>
<p>v3:{{ v3 }}</p>
</div>
</template>

<!-- 之前只能这样写: -->
<template>
<div>
<h1>ToRefs</h1>
<p>v1:{{ state.v1 }}</p>
<p>v2:{{ state.v2 }}</p>
<p>v3:{{ state2.v3 }}</p>
</div>
</template>
1
2
3
4
5
6
// 封装 hooks 后,别人调用可以这样写:
const { v1, v2, v3 } = useDemo()

// 封装 hooks 后,之前只能这样写:
// state 不可以再进行解构,否则失去响应
const { state, state2 } = useDemo()

总之,toRef toRefs 在项目中应该非常常用!

新的内置组件:Teleport (传送门)

比如官网的例子:

1
2
3
4
5
6
7
8
<body>
<div style="position: relative;">
<h3>Tooltips with Vue 3 Teleport</h3>
<div>
<modal-button></modal-button>
</div>
</div>
</body>

这个 modal-button 最后生成 html 后,就在 body > div > div 下,如果想把它生成在 body 最后一个节点后,基本上比较难实现。

之所以认为比较难实现,是因为我只会 vue 2 的基础用法,复杂的根本不会…

React 一直都有一个 createPortal,可以很方便的解决这个问题。

这次,Vue 3 提供了这样一个组件来实现。

is 系列 isRef、isProxy、isReactive、isReadonly

最早使用 rc2 版本测试过一次,后来发现 rc5 版本发生了一些变化,倒是无法解释了。所以在出正式版之前,不会在测试了。

等正式版出来后再测试看看,如果能解释就放出来,解释不了就等等看其他人有没有高见。

估计是为了更容易上手新的 composition-api,Vue 3.0 还提供了一套生命周期概念。这点比 React-hooks 容易多了。不过这些生命周期应该在实际项目中很少被用到,因为没有生命周期的 React-hooks 一样可以做的很好。

1
2
3
4
5
6
7
8
beforeCreate -> 使用 setup()
created -> 使用 setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted

beforeCreate:我从来没有接触过,这个不多说,感觉是模拟不了的。

created:现在直接在 setup() 里写就行了。

beforeMount mounted:对于 Vue 确实需要,否则无法判断元素是否挂载完成。虽然可以进行模拟,但比较场景化,不同场合写法会有出入。React 是通过 useEffect(()=>{}, []) 来模拟。对应的 Vue 可以用 watchEffect 模拟。watch 应该不行,因为默认不会执行第一次监听。具体实现可以参考下文例子。要注意的是,功能虽然实现了,但执行次数超过一次,需要特殊处理。

destroyed:由于 Vue watchEffect 也支持清理副作用 onInvalidate,所以可能模拟出组件销毁,不过估计也要借助 ref 等其他辅助参数来实现,成本一样非常高。

beforeUpdate:我也从来没用过,也不多说了,感觉是模拟不了的。

updated:肯定可以通过 watch 模拟出来,就是把所有响应式数据都监听就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
export default {
name: 'Lifecycles',
setup () {
console.log('[Lifecycles] setup')

const state = reactive({ value: 0, list: [] })
const textRef = ref(null)

const onTestClick = () => {
state.value++
}

watchEffect(() => {
console.log('Lifecycles 模拟mounted -- L1') // 这里会执行2次,第一次相当于 beforeMount,第二次是mounted
// 所以这里要判断,如果是 beforeMount,是没有 textRef.value 值的
if (textRef.value) textRef.value.textContent = '12345'
})

watchEffect(() => {
// 比如发送请求
console.log('Lifecycles 模拟mounted -- L2') // 如果 state.list 后续不会有任何修改,这里可以模拟mounted
setTimeout(() => {
state.list = [1, 2, 3, 4, 5]
})
})

return {
state,
textRef,
onTestClick,
}
}
}

–END–

分享到

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK