本文是结合实践中和学习技术文章总结出来的笔记(个人使用),如有雷同纯属正常((✿◠‿◠))
喜欢的话点个赞,谢谢!
时下Vue框架都是使用Vue3版本来开发项目了,为了加深对Vue3基本知识的了解,特写了这个笔记
一个组件从开始到结束,正常的生命周期流程应该是这样:
- //1.开始创建组件,在 beforeCreate 和 created 之前执行,创建的是 data 和 method
- setup()
- //2.在组件挂载之前执行
- onBeforeMount()
- //3.在组件挂载之后执行
- onMount()
- //4.在组件更新之前执行
- onBeforeUpdate()
- //5.在组件更新之后执行
- onUpdated()
- //6.在组件卸载之前执行
- onBeforeUnmount()
- //7.在组件卸载之后执行
- onUnmounted()
还有三个函数是特殊情况执行的:
onErrorCaptured
当捕获一个来自一个来自子孙组件的异常时触发的钩子函数
onActivated
每次进入该组件页面都会触发
onDeactivated
比如从A组件切换到B组件,A组件消失时执行(等于是离开组件时触发)
vue2生命周期对比vue3生命周期,主要是beforeCreate和created被setup取代,还有一些方法名的变化:
- //1.开始创建组件,在 beforeCreate 和 created 之前执行,创建的是 data 和 method
- beforeCreate + created = setup()
- //2.在组件挂载之前执行
- beforeMount() => onBeforeMount()
- //3.在组件挂载之后执行
- mounted() => onMount()
- //4.在组件更新之前执行
- beforUpdated() => onBeforeUpdate()
- //5.在组件更新之后执行
- Updated() => onUpdated()
- //6.在组件卸载之前执行
- beforeDestory() => onBeforeUnmount()
- //7.在组件卸载之后执行
- destoryed() => onUnmounted()
- //
- activated() => onActivated()
- deactivated() => onDeactivated()
- //当捕获一个来自一个来自子孙组件的异常时触发的钩子函数
- errorCaptured() => onErrorCaptured()
在做React开发的时候经常听到朋友抱怨vue2历史项目难以维护,代码分层逻辑乱的一团糟,本人也有幸维护过几个vue2项目,深有感触
一个整体的逻辑会被拆分到data、method、watch里面去,如果开发者经验不足或者不编写注释,代码维护程度简直令人抓狂(^_^)
组合式api的特点就是可以将单个功能的状态、方法、计算属性都融合在一起组成一个hook(抽离逻辑自定义hook),然后再将这个hook引入到组合api里面,这样做的好处是便于阅读和代码维护,如下图所示:
这图是社区复制而来(^_^)
Vue3新的一个配置项,所有的组合式函数都在此使用,只在初始化的时候执行一次。setup可以在选项式api里面使用,也可以在组合式api里面使用,不过官方更推荐在组合api风格里面使用,如下图所示:
选项式api风格:
- import { ref } from 'vue'
- export default {
- setup () {
- const count = ref(0)
- return {
- count
- }
- }
- }
- <template>
- <div>{{ count }}div>
- <button @click="count++">
- +
- button>
- template>
- <style lang='less' scoped>
- style>
组合式api风格:
- <template>
- <div>{{ count }}div>
- <button @click="count++">
- +
- button>
- template>
- <style lang='less' scoped>style>
区别:
此处官网介绍的比较详细,可以跳转查阅Vue3.js组合式api
Vue2与Vue3响应式的区别在于,vue2的响应式是基于Object.definePropert做数据劫持,而Vue3是基于Es6的Proxy来进行数据劫持
ref接收一个值,返回一个响应式对象,可以处理简单的数据类型,底层还是基于Object.definePropert做数据劫持,如果在处理对象类型的时候会求助reactive。如下图所示:
- <template>
- <div>{{ count }}div>
- <button @click="count++">
- +
- button>
- template>
- <style lang='less' scoped>style>
reactive是用来做深层响应式代理的,如果传入的是基本数据类型如数字、字符串等它将不是响应式对象,reactive返回一个Proxy对象,Proxy对象是专门用来处理代理的,内部可以实现数据的增删改查操作,所以reactive可以实现基本的拦截和自定义。如下图所示:
- <template>
- <div>{{ count.arr }}div>
- <button @click="add(1)">
- +
- button>
- template>
- <style lang='less' scoped>style>
shallowRef传入对象不会求助reactive,只会对value值响应,shallowReactive只处理第一层的对象响应,更深层次不会进行响应。这两个api所用甚少,这里就不过多介绍了
computed函数是用来做计算的,通过监听某一个值得到一个新的值,有两种写法
- <template>
- <div>{{ count }}div>
- <button @click="count++">
- +1
- button>
- <button @click="setCount2++">
- +3
- button>
- template>
- <style lang='less' scoped>style>
watch函数是用来监听一个响应式对象,或者多个(多个时第一个参数为数数组),当监听对象发生变化时返回一个回调函数
- <template>
- <div>{{ count }}div>
- <button @click="count++">
- +
- button>
- template>
- <style lang='less' scoped>style>
watchEffect函数用于监听传入的函数内部所有的响应式对象的变化,就是回调里面用了哪个对象就监听哪个对象
- <template>
- <div>{{ count }}div>
- <button @click="count++">
- +
- button>
- template>
- <style lang='less' scoped>style>
vue的组件通信与React不太一样,React因为JSX语法的原因不需要特殊处理,vue的话因为采用的模板语法,所以需要使用一些方法来处理
在vue3里面传递数据的时候,可以使用definePorps来接收父组件传入的props参数:
在父组件使用子组件时,使用props对其传入数据:
<Child :count="count" />
子组件接收:
- <template>
- <div>{{ props.count }}div>
- template>
注意点:props为只读属性,不可更改,如果需要更改传入的数据,可以在当前组件重新定义一个ref对象
子组件向父组件发送消息会稍微麻烦一点,毕竟框架数据流通都是基于单向数据流的理念的,所以需要采用额外的方法来处理
通过向子组件发送一个回调函数的方式,直接在子组件调用
- <template>
- <div />
- 父组件显示:{{ count }}
- <Child
- :count="count"
- :add="add"
- />
- template>
- <style lang='less' scoped>style>
子组件:
- <template>
- <button :onclick="props.add">
- +
- button>
- template>
- <style lang='less' scoped>
- style>
可以实现隔代组件通信
父组件:
- <template>
- <div />
- 父组件显示:{{ count }}
- <Child
- :count="count"
- />
- template>
- <style lang='less' scoped>style>
子组件:
- <template>
- <button :onclick="add">
- +
- button>
- template>
- <style lang='less' scoped>
- style>
安装
yarn add pinia
创建store
- import { createPinia } from 'pinia'
- // 创建store
- const store = createPinia()
- // 对外暴露,安装仓库
- export default store
注册
- ...
- import pinia from './store/pinia'
-
- ...
-
- app.use(router)
- .use(Antd)
- .use(store)
- + .use(pinia)
- .mount('#app')
添加models
- import { defineStore } from 'pinia'
- const Store = defineStore('test', {
- state: () => {
- return {
- count: 0
- }
- },
- actions: {
- add (count:number) {
- this.count = this.count + count
- }
- },
- getters: {
-
- }
- })
- export default Store
页面显示
- <template>
- 父组件显示:{{ store.count }}
- <button :onclick="add">
- +
- button>
- 子组件显示:
- <Child />
- template>
- <style lang='less' scoped>style>
子组件:
- <template>
- {{ store.count }}
- template>
- <style lang='less' scoped>
- style>