浅析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>
相关推荐
EricWang135820 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning20 分钟前
React.lazy() 懒加载
前端·react.js·前端框架
web行路人30 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
番茄小酱00131 分钟前
Expo|ReactNative 中实现扫描二维码功能
javascript·react native·react.js
Yawesh_best40 分钟前
思源笔记轻松连接本地Ollama大语言模型,开启AI写作新体验!
笔记·语言模型·ai写作
子非鱼9211 小时前
【Ajax】跨域
javascript·ajax·cors·jsonp
超雄代码狂1 小时前
ajax关于axios库的运用小案例
前端·javascript·ajax
长弓三石1 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
小马哥编程1 小时前
【前端基础】CSS基础
前端·css
嚣张农民1 小时前
推荐3个实用的760°全景框架
前端·vue.js·程序员