浅析Vue3基础知识(vue3笔记之入门篇)

本文是结合实践中和学习技术文章总结出来的笔记(个人使用),如有雷同纯属正常((✿◠‿◠))

喜欢的话点个赞,谢谢!

时下Vue框架都是使用Vue3版本来开发项目了,为了加深对Vue3基本知识的了解,特写了这个笔记

1. 生命周期

1.1. vue3生命周期

一个组件从开始到结束,正常的生命周期流程应该是这样:

javascript 复制代码
//1.开始创建组件,在 beforeCreate 和 created 之前执行,创建的是 data 和 method
setup()
//2.在组件挂载之前执行
onBeforeMount()
//3.在组件挂载之后执行
onMount()
//4.在组件更新之前执行
onBeforeUpdate()
//5.在组件更新之后执行
onUpdated()
//6.在组件卸载之前执行
onBeforeUnmount()
//7.在组件卸载之后执行
onUnmounted()

还有三个函数是特殊情况执行的:

onErrorCaptured

当捕获一个来自一个来自子孙组件的异常时触发的钩子函数

**<keep-alive>:**被包含在<keep-alive>中的组件,会多出2个生命周期钩子函数:

onActivated

每次进入该组件页面都会触发

onDeactivated

比如从A组件切换到B组件,A组件消失时执行(等于是离开组件时触发)

1.2. vue2生命周期

vue2生命周期对比vue3生命周期,主要是beforeCreate和created被setup取代,还有一些方法名的变化:

javascript 复制代码
//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()
//<keep-alive>
activated()     =>  onActivated() 
deactivated()   =>  onDeactivated()
//当捕获一个来自一个来自子孙组件的异常时触发的钩子函数
errorCaptured()   =>  onErrorCaptured()

2. 选项式api和组合式api

在做React开发的时候经常听到朋友抱怨vue2历史项目难以维护,代码分层逻辑乱的一团糟,本人也有幸维护过几个vue2项目,深有感触

2.1. 选项式api的痛点:

一个整体的逻辑会被拆分到data、method、watch里面去,如果开发者经验不足或者不编写注释,代码维护程度简直令人抓狂(^_^)

2.2. 组合式api

组合式api的特点就是可以将单个功能的状态、方法、计算属性都融合在一起组成一个hook(抽离逻辑自定义hook),然后再将这个hook引入到组合api里面,这样做的好处是便于阅读和代码维护,如下图所示:

这图是社区复制而来(^_^)

2.2.1. setup

Vue3新的一个配置项,所有的组合式函数都在此使用,**只在初始化的时候执行一次。**setup可以在选项式api里面使用,也可以在组合式api里面使用,不过官方更推荐在组合api风格里面使用,如下图所示:

选项式api风格:

javascript 复制代码
<script>
import { ref } from 'vue'
export default {
    setup () {
        const count = ref(0)
        return {
            count
        }
    }
}
</script>
<template>
  <div>{{ count }}</div>
  <button @click="count++">
    +
  </button>
</template>
<style lang='less' scoped>
</style>

组合式api风格:

javascript 复制代码
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <div>{{ count }}</div>
  <button @click="count++">
    +
  </button>
</template>
<style lang='less' scoped></style>

区别:

此处官网介绍的比较详细,可以跳转查阅 Vue3.js组合式api

  • <srcipt setup>可以直接使用顶层变量和函数,选项式代码则还需要导出才能使用
  • <srcipt setup>对ts支持更好
  • <srcipt setup>打包出来的体积更小
  • <srcipt setup>肉眼可见的代码直观性和简洁

3. 响应式

Vue2与Vue3响应式的区别在于,vue2的响应式是基于Object.definePropert做数据劫持,而Vue3是基于Es6的Proxy来进行数据劫持

3.1.1. ref

ref接收一个值,返回一个响应式对象,可以处理简单的数据类型,底层还是基于Object.definePropert做数据劫持,如果在处理对象类型的时候会求助reactive。如下图所示:

javascript 复制代码
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <div>{{ count }}</div>
  <button @click="count++">
    +
  </button>
</template>
<style lang='less' scoped></style>
3.1.2. reactive

reactive是用来做深层响应式代理的,如果传入的是基本数据类型如数字、字符串等它将不是响应式对象,reactive返回一个Proxy对象,Proxy对象是专门用来处理代理的,内部可以实现数据的增删改查操作,所以reactive可以实现基本的拦截和自定义。如下图所示:

javascript 复制代码
<script setup lang="ts">
import { ref } from 'vue'
const count = ref({
    arr: [1, 2, 3, 4]
})
const add = (value:number) => {
    count.value.arr.push(value)
}
</script>
<template>
  <div>{{ count.arr }}</div>
  <button @click="add(1)">
    +
  </button>
</template>
<style lang='less' scoped></style>
3.1.3. shallowReactive 与 shallowRef

shallowRef传入对象不会求助reactive,只会对value值响应,shallowReactive只处理第一层的对象响应,更深层次不会进行响应。这两个api所用甚少,这里就不过多介绍了

4. 计算属性和监听

4.1. computed函数

computed函数是用来做计算的,通过监听某一个值得到一个新的值,有两种写法

  1. 只读写法: computed(()=>a + b)
  2. 可读可改写法:computed({get:()=>a + b,set:(val)=> {xxxxx}})
javascript 复制代码
<script setup lang="ts">
import { computed, ref } from 'vue'
const count = ref(0)
const setCount2 = computed({
    get: () => {
        return count.value + 1
    },
    set: (value) => {
        count.value = value + 1
    }
})
</script>
<template>
  <div>{{ count }}</div>
  <button @click="count++">
    +1
  </button>
  <button @click="setCount2++">
    +3
  </button>
</template>
<style lang='less' scoped></style>
4.2. watch函数

watch函数是用来监听一个响应式对象,或者多个(多个时第一个参数为数数组),当监听对象发生变化时返回一个回调函数

javascript 复制代码
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
//监听
watch(count,(newvalue,oldvalue)=>{
    console.log(newvalue)
})
</script>
<template>
  <div>{{ count }}</div>
  <button @click="count++">
    +
  </button>
</template>
<style lang='less' scoped></style>
4.3. watchEffect

watchEffect函数用于监听传入的函数内部所有的响应式对象的变化,就是回调里面用了哪个对象就监听哪个对象

javascript 复制代码
<script setup lang="ts">
import { ref, watchEffect } from 'vue'
const count = ref(0)
const add = (count:number) => {
    console.log(count)
}
// 监听
watchEffect(() => {
    add(count.value)
})
</script>
<template>
  <div>{{ count }}</div>
  <button @click="count++">
    +
  </button>
</template>
<style lang='less' scoped></style>

5. 组件通信

vue的组件通信与React不太一样,React因为JSX语法的原因不需要特殊处理,vue的话因为采用的模板语法,所以需要使用一些方法来处理

5.1. 父子通信

在vue3里面传递数据的时候,可以使用definePorps来接收父组件传入的props参数:

在父组件使用子组件时,使用props对其传入数据:

复制代码
  <Child :count="count" />

子组件接收:

javascript 复制代码
<script setup lang='ts'>
import { defineProps } from 'vue'
const props = defineProps({
    count: {
        type: Number,
        default: 0
    }
})
</script>
<template>
  <div>{{ props.count }}</div>
</template>

注意点:props为只读属性,不可更改,如果需要更改传入的数据,可以在当前组件重新定义一个ref对象

5.2. 子父通信

子组件向父组件发送消息会稍微麻烦一点,毕竟框架数据流通都是基于单向数据流的理念的,所以需要采用额外的方法来处理

5.2.1. 添加回调函数

通过向子组件发送一个回调函数的方式,直接在子组件调用

javascript 复制代码
<script setup lang="ts">
import { ref } from 'vue'
import Child from './test.vue'
const count = ref(0)
const add = () => {
    count.value = count.value + 1
}
</script>
<template>
  <div />
  父组件显示:{{ count }}
  <Child
    :count="count"
    :add="add"
  />
</template>
<style lang='less' scoped></style>

子组件:

javascript 复制代码
<script setup lang='ts'>
import { defineProps } from 'vue'
const props = defineProps({
    add: {
        type: Function,
        default: () => {}
    }
})
</script>
<template>
  <button :onclick="props.add">
    +
  </button>
</template>
<style lang='less' scoped>
</style>
5.2.2. provide与inject

可以实现隔代组件通信

父组件:

javascript 复制代码
<script setup lang="ts">
import { ref, provide } from 'vue'
import Child from './test.vue'
const count = ref(0)
provide('Count', count)
</script>
<template>
  <div />
  父组件显示:{{ count }}
  <Child
    :count="count"
  />
</template>
<style lang='less' scoped></style>

子组件:

javascript 复制代码
<script setup lang='ts'>
import { inject } from 'vue'
const count = inject('Count')
const add = () => {
    count.value = count.value + 1
}
</script>
<template>
  <button :onclick="add">
    +
  </button>
</template>
<style lang='less' scoped>
</style>
5.2.3. 使用pinia通信

安装

javascript 复制代码
yarn add pinia

创建store

javascript 复制代码
import { createPinia } from 'pinia'
// 创建store
const store = createPinia()
// 对外暴露,安装仓库
export default store

注册

javascript 复制代码
...
import pinia from './store/pinia'

...

app.use(router)
    .use(Antd)
    .use(store)
+   .use(pinia)
    .mount('#app')

添加models

javascript 复制代码
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

页面显示

javascript 复制代码
<script setup lang="ts">
import infostore from '@/store/piniamodels'
import Child from './test.vue'
const store = infostore()
const add = () => {
    store.add(1)
}
</script>
<template>
  父组件显示:{{ store.count }}
  <button :onclick="add">
    +
  </button>
  子组件显示:
  <Child />
</template>
<style lang='less' scoped></style>

子组件:

javascript 复制代码
<script setup lang='ts'>
import infostore from '@/store/piniamodels/index'
const store = infostore()
</script>
<template>
  {{ store.count }}
</template>
<style lang='less' scoped>
</style>
相关推荐
翻滚吧键盘27 分钟前
js代码09
开发语言·javascript·ecmascript
万少1 小时前
第五款 HarmonyOS 上架作品 奇趣故事匣 来了
前端·harmonyos·客户端
OpenGL1 小时前
Android targetSdkVersion升级至35(Android15)相关问题
前端
future14121 小时前
每日问题总结
经验分享·笔记
rzl021 小时前
java web5(黑马)
java·开发语言·前端
Amy.Wang1 小时前
前端如何实现电子签名
前端·javascript·html5
海天胜景1 小时前
vue3 el-table 行筛选 设置为单选
javascript·vue.js·elementui
今天又在摸鱼1 小时前
Vue3-组件化-Vue核心思想之一
前端·javascript·vue.js
蓝婷儿1 小时前
每天一个前端小知识 Day 21 - 浏览器兼容性与 Polyfill 策略
前端
百锦再1 小时前
Vue中对象赋值问题:对象引用被保留,仅部分属性被覆盖
前端·javascript·vue.js·vue·web·reactive·ref