banner
banner
banner
NEWS LETTER

VUE3-快速上手

Scroll down

vue概念

  • 用于构建用户界面的 JavaScript 框架–渐进式框架。
  • 基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型。

vue核心功能

  • 声明式渲染:拓展了模板语法,描述HTML跟js状态间的关系
  • 响应性:自动跟踪js状态并在发生变化时响应式的更新DOM

渐进式框架

  • 无需构建步骤,渐进式增强静态的 HTML
  • 在任何页面中作为 Web Components 嵌入
  • 单页应用 (SPA)
  • 全栈 / 服务端渲染 (SSR)
  • Jamstack / 静态站点生成 (SSG)
  • 开发桌面端、移动端、WebGL,甚至是命令行终端中的界面

API风格

  • 选项式 — 不适用构建工具/低复杂度

    • 包含多个选项的对象来描述组件的逻辑如,data、methods、mounted,选项中定义的属性都会暴露在函数内部的this,this指向当前组件实例
  • 组合式API — 完整单页面应用

    • 使用导入的API函数来描述组件逻辑。通常搭配<script setup>使用

vue3优点

  • 性能的提升
    • 打包大小减少41%
    • 初次渲染快55%, 更新渲染快133%
    • 内存减少54%
  • 源码的升级
    • 使用Proxy代替defineProperty实现响应式
    • 重写虚拟DOM的实现和Tree-Shaking
  • 拥抱TypeScript
  • 新的特性
    • Composition API(组合API)
      • setup配置
      • ref与reactive
      • watch与watchEffect
      • provide与inject
    • 新的内置组件
      • Fragment
      • Teleport
        • Suspense
    • 其他改变
      • 新的生命周期钩子
      • data 选项应始终被声明为一个函数
      • 移除keyCode支持作为 v-on 的修饰符

创建项目 + vite

  • vite
  • node版本要16以上
  • 使用create-vue
  • 安装:
    1
    npm create vue@latest

模板语法

  • 文本插值:{{}}
  • 原始html:v-html=””
  • Attribute绑定:(v-bind:xxx=”” 简写 :xxx=””)
    • 正常情况:值为null或undefined,attribute将会从渲染的元素上移除
    • 布尔型:值为真值或一个空字符串,元素会包含这个attribute;为其他假值时忽略
    • 动态绑定多个值:对象包含多个属性。使用不带参的v-bind,绑定到单个元素上。
      • v-bind=”obj”
  • 支持javascript表达式或者调用函数

指令(Directives)

  • 期望值为一个javascript表达式,表达式的值变化时响应式更新DOM
  • javascript表达式使用v-bind(:),函数使用v-on(@)
  • 参数::xxx=””
  • 动态参数::[字符串或null]=””
    • 三限制:禁空格、禁引号、禁大写
  • 修饰符.:触发事件

响应式原理

常用 Composition API

setup

  • 代表使用组合式API,<script setup>是setup函数的语法糖
  • <script setup>获取props,emit,context
    • 子组件引入:
      1
      import { useContext, defineProps, defineEmit } from 'vue'
    • emit:
      1
      2
      3
      4
      5
      // 定义
      const emit = defineEmit(['父组件在子组件标签上传的事件名'])

      // 在子组件的某个事件触发:
      emit('事件名', 子组件传递的数据) // 父组件通过事件参数拿到
    • ctx:
      1
      const ctx = useContext()
    • props:
      1
      const props = defineProps({ 父组件在子组件标签上传的属性名: 该属性的类型 })
  • 注意点:
    • setup执行的时机
      • 在beforeCreate之前执行一次,this是undefined。
    • setup的参数
      • props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性
      • context:上下文对象
        • attrs:值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 this.$attrs
        • slots:收到的插槽内容, 相当于 this.$slots
        • emit:分发自定义事件的函数, 相当于 this.$emit

ref函数

  • 作用: 声明一个响应式的状态
  • 使用:
    1
    import { ref } from 'vue'
  • 语法:
    1
    const xxx = ref(initValue)
    • JS中操作数据:xxx.value
    • 模板中读取数据: 不需要.value,直接:
      1
      <div>{{xxx}}</div>
  • 优点:
    • 深层响应性
      • 应用于任意值,即改变就会检测
      • shallow ref 可放弃深层响应性
      • 非原始值将通过 reactive() 转换为响应式代理
    • DOM更新时机
      • 更改响应式状态后,DOM会自动更新,但并不是同步
      • 等待一个状态改变后的DOM更新完成,使用nextTick()
  • 备注:
    • 接收的数据可以是:基本类型、也可以是对象类型。
    • 『基本类型』的数据:响应式依然是靠 Object.defineProperty()的get与set 完成的。
    • 『对象类型』的数据:使用 reactive 处理

reactive函数

  • 作用: 定义一个『对象类型』的响应式数据,返回一个『代理对象』(Proxy的实例对象,简称proxy对象)
  • 语法:
    1
    const 代理对象= reactive(源对象) // 接收一个对象(或数组)
  • 使用:『代理对象』
  • 局限性:只能用于对象类型(对象、数组和Map、Set这样的集合类型),并且不能替换整个对象,解构不友好
  • 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。

reactive 和 ref 区别

  • 从定义数据角度对比:
    • ref用来定义:『基本类型数据』
    • reactive用来定义:『对象(或数组)类型数据』
    • 注:ref也可以定义『对象(或数组)类型』数据, 它内部会自动通过 reactive 转为代理对象
  • 从原理角度对比:
    • ref通过 Object.defineProperty()的get与set 来实现响应式(数据劫持)
    • reactive通过使用 Proxy 来实现响应式(数据劫持), 并通过『Reflect操作源对象』内部的数据
  • 从使用角度对比:
    • ref定义的数据:操作数据『需要.value』,读取数据时模板中直接读取『不需要.value』
    • reactive定义的数据:操作数据与读取数据:『均不需要.value』

⭐ 计算属性computed — 依赖响应式状态的复杂逻辑

  • 与Vue2中computed配置功能一致☞VUE2-基础(主了解)
  • 计算属性值会基于其响应式依赖被缓存,只有依赖改变才会去重新计算
  • 写法:
    • 引入钩子:
      1
      import { computed } from 'vue'
    • 使用:
      1
      computed(()=> {})

侦听器 watch — 在状态变化时执行一些“副作用”

  • 与Vue2中watch配置功能一致☞VUE2-基础(主了解)
  • 两个小“坑”:
    • 监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)
    • 监视reactive定义的响应式数据中某个属性时:deep配置有效
  • 写法:
    • 引入钩子:
      1
      import { watch } from 'vue'
    • 基本使用:
      1
      watch(变量,(newValue,oldValue)=>{},{immediate:true})
    • 监视多个ref定义的响应式数据:
      1
      watch([变量1,变量2],(newValue,oldValue)=>{})
    • 监视reactive定义的响应式数据中的某个属性(监视的是对象中的某个属性,所以deep配置有效)
      1
      watch(()=>对象.属性,(newValue,oldValue)=>{},{immediate:true,deep:true})
    • 监视reactive定义的响应式数据中的多个属性
      1
      watch([()=>对象.属性,()=>对象.属性2],(newValue,oldValue)=>{},{immediate:true,deep:true})

深层侦听器

  • 使用 deep: true 开启,开销很大,无必要不使用

即时回调的侦听器

  • 使用 immediate: true 开启

watchEffect函数

  • watch的套路是:既要指明监视的属性,也要指明监视的回调。
  • watchEffect的套路是:『不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性』
  • 使用:watchEffect(()=>{})
  • 注:仅会在其同步执行期间,才追踪依赖。在使用异步回调时,只有在第一个 await 正常工作前访问到的属性才会被追踪。

回调的触发时机

  • 默认,用户创建的侦听器回调,都会在『Vue 组件更新前被调用』
  • 在侦听器回调中能访问被 『Vue 更新之后的 DOM,指明 flush: ‘post’ 选项』

停止侦听器

  • 场景:用异步回调创建一个侦听器,它不会绑定到当前组件上,必须手动停止它,以防内存泄漏
  • 停止一个侦听器:调用 watch 或 watchEffect 返回的函数
    1
    2
    const unwatch = watchEffect(() => {})
    unwatch()

⭐ 生命周期钩子

vue生命周期钩子

  • Vue3可继续使用Vue2的生命周期钩子,但有两个更名:
    • beforeDestroy 改名为 beforeUnmount
    • destroyed 改名为 unmounted

Vue3的Composition API 形式的生命周期钩子,与Vue2中钩子对应关系如下:(vue3:vue2)

  • beforeCreate ==> setup()
  • created ==> setup()
  • beforeMount ==> onBeforeMount
  • mounted ==> onMounted
  • beforeUpdate ==> onBeforeUpdate
  • updated ==> onUpdated
  • beforeUnmount ==> onBeforeUnmount
  • unmounted ==> onUnmounted

vue3生命周期钩子的作用

  • beforeCreate
    • 在组件实例初始化完成后立即调用,data() 和 computed 等选项处理之前立即调用
  • created
    • 已完成响应式数据、计算属性、方法和侦听器。
    • 然而,此时挂载阶段还未开始,因此 $el 属性仍不可用
  • beforeMount
    • 在组件被挂载之前调用,还没创建DOM节点
  • mounted
    • 在组件挂载之后调用,所有同步子组件都已经被挂载。
    • 其自身的 DOM 树已经创建完成并插入了父容器中。
    • 处理副作用
  • beforeUpdate
    • 在组件即将因为一个响应式状态变更而更新其DOM树之前调用。
    • 在 Vue 更新 DOM 之前访问 DOM 状态
  • update
    • 在组件因为一个响应式状态变更而更新其 DOM 树之后调用。
    • 父组件的更新钩子将在其子组件的更新钩子之后调用。
    • 在组件的任意 DOM 更新后被调用
  • beforeUnmount
    • 在一个组件实例被卸载之前调用
    • 当这个钩子被调用时,组件实例依然还保有全部的功能
  • unmounted
    • 在一个组件实例被卸载之后调用,
    • 可以在这个钩子中手动清理一些副作用,例如计时器、DOM 事件监听器或者与服务器的连接。
  • activated
    • 组件实例是 KeepAlive标签 缓存树的一部分,当组件被插入到 DOM 中时调用
  • deactivated
    • 组件实例是 KeepAlive标签 缓存树的一部分,当组件从 DOM 中被移除时调用

组件生命周期执行路线

生命周期(父子组件):

  • 父组件beforeCreate –> 父组件created –> 父组件beforeMount –> 子组件beforeCreate –> 子组件created –> 子组件beforeMount –> 子组件 mounted –> 父组件mounted –>父组件beforeUpdate –>子组件beforeDestroy–> 子组件destroyed –> 父组件updated

加载渲染过程

  • 父beforeCreate –> 父created –> 父beforeMount –> 子beforeCreate –> 子created –> 子beforeMount –> 子mounted –> 父mounted

挂载阶段

  • 父created –> 子created –> 子mounted –> 父mounted

父组件更新阶段

  • 父beforeUpdate –> 父updated

子组件更新阶段

  • 父beforeUpdate –> 子beforeUpdate –> 子updated –> 父updated

销毁阶段

  • 父beforeDestroy –> 子beforeDestroy –> 子destroyed –> 父destroyed

模板引用

  • ref:直接访问底层DOM元素,DOM 元素或子组件实例被挂载后,可以直接引用
  • 使用:
    • 引入:
      1
      import { ref, onMounted } from 'vue'
    • 使用:
      1
      <view ref="" />
  • v-for中的模板引用:

    • ref的值是数组
    • 『ref 数组并不保证与源数组相同的顺序』
  • 函数模板引用:

    • 『:ref绑定为一个函数』,函数会收到元素引用作为其第一个参数
      1
      <input :ref="(el) => {}"/>
  • 组件上的ref:

    • 用在组件上获取的是组件实例

其它 Composition API

shallowReactive 与 shallowRef

  • shallowReactive:只处理对象最外层属性的响应式(浅响应式)。
  • shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理。
  • 使用场景:
    • 如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive
    • 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换 ===> shallowRef

readonly 与 shallowReadonly

  • readonly: 让一个响应式数据变为只读的(深只读)
  • shallowReadonly:让一个响应式数据变为只读的(浅只读)
  • 应用场景: 不希望数据被修改时。

toRaw 与 markRaw

  • toRaw:
    • 作用:将一个由 reactive 生成的『响应式对象转为普通对象』
    • 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新
  • markRaw:
    • 作用:标记一个对象,使其永远不会再成为响应式对象
    • 应用场景:
      • 有些值不应被设置为响应式的,例如复杂的第三方类库等
      • 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能

customRef

  • 作用:创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制
  • 实现防抖效果:
    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
    34
    35
    <template>
    <input type="text" v-model="keyword">
    <h3>{{keyword}}</h3>
    </template>

    <script>
    import {ref,customRef} from 'vue'
    export default {
    name:'Demo',
    setup(){
    //自定义一个myRef
    function myRef(value,delay){
    let timer
    //通过customRef去实现自定义
    return customRef((track,trigger)=>{
    return{
    get(){
    track() //告诉Vue这个value值是需要被“追踪”的
    return value
    },
    set(newValue){
    clearTimeout(timer)
    timer = setTimeout(()=>{
    value = newValue
    trigger() //告诉Vue去更新界面
    },delay)
    }
    }
    })
    }
    let keyword = myRef('hello',500) //使用程序员自定义的ref
    return { keyword }
    }
    }
    </script>

provide 与 inject

  • 作用:『实现祖先与后代组件间通信』
  • 套路:父组件有一个 provide 选项来提供数据,后代组件有一个 inject 选项来开始使用这些数据
  • 具体写法:
    1. 祖组件中:使用
      1
      provide('通信的别名',要传递的变量)
    2. 后代组件中:
      1
      const 得到的变量 = inject('通信的别名')

响应式API:工具函数

  • isRef(): 检查一个值是否为一个 ref 对象
  • unref(): 如果参数是 ref,则返回内部值,否则返回参数本身
  • isReactive(): 检查一个对象是否是由 reactive 创建的响应式代理
  • isReadonly(): 检查一个对象是否是由 readonly 创建的只读代理
  • isProxy(): 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理
  • toRef():创建一个 ref 对象,其value值指向另一个对象中的某个属性。
    • 语法:
      1
      const name = toRef(person,'name')
  • toRefs(): 与 toRef 功能一致,值指向一个对象
    • 语法:
      1
      toRefs(person)

新的组件

Fragment

  • 在Vue2中: 组件必须有一个根标签
  • 在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中
  • 好处: 减少标签层级, 减小内存占用

Teleport

  • 定义: 将『组件html结构』移动到指定位置的技术
  • 使用:teleport标签包裹的内容是移动的内容,标签上指定to=”移动位置”

Suspense

  • 等待异步组件时渲染一些额外内容
  • 使用步骤:
    • 引入钩子:
      1
      import {defineAsyncComponent} from 'vue'
    • 异步引入组件:
      1
      const 组件名 = defineAsyncComponent(()=>import('组件路径'))
      • 使用 Suspense 包裹组件,并配置好对应插槽的内容

其他

全局API的转移

  • Vue 2 有许多全局 API 和配置在vue3中调整。
    • 将全局的API,即:Vue.xxx 调整到应用实例(app)上
      全局 API 实例 API (app)
      Vue.config.xxxx app.config.xxxx
      Vue.config.productionTip 移除
      Vue.component app.component
      Vue.directive app.directive
      Vue.mixin app.mixin
      Vue.use app.use
      Vue.prototype app.config.globalProperties

其他改变

  • data选项应始终被声明为一个函数。
  • 过度类名的更改:.v-enter-from,.v-leave-to(vue3写法)
  • 移除keyCode作为 v-on 的修饰符,同时也不再支持 config.keyCodes
  • 移除 v-on.native修饰符
  • 移除过滤器(filter)
其他文章
cover
VUE3-路由
  • 24/11/01
  • 14:39
  • VUE
cover
VUE3-Pinia
  • 24/11/01
  • 14:39
  • VUE
目录导航 置顶
  1. 1. vue概念
  2. 2. vue核心功能
  3. 3. 渐进式框架
  4. 4. API风格
    1. 4.1. 选项式 — 不适用构建工具/低复杂度
    2. 4.2. 组合式API — 完整单页面应用
  5. 5. vue3优点
  6. 6. 创建项目 + vite
  7. 7. 模板语法
  8. 8. 指令(Directives)
  9. 9. 响应式原理
  10. 10. 常用 Composition API
    1. 10.1. setup
    2. 10.2. ref函数
    3. 10.3. reactive函数
    4. 10.4. reactive 和 ref 区别
    5. 10.5. ⭐ 计算属性computed — 依赖响应式状态的复杂逻辑
    6. 10.6. 侦听器 watch — 在状态变化时执行一些“副作用”
  11. 11. ⭐ 生命周期钩子
    1. 11.1. Vue3的Composition API 形式的生命周期钩子,与Vue2中钩子对应关系如下:(vue3:vue2)
    2. 11.2. vue3生命周期钩子的作用
    3. 11.3. 组件生命周期执行路线
  12. 12. 模板引用
    1. 12.1. v-for中的模板引用:
    2. 12.2. 函数模板引用:
    3. 12.3. 组件上的ref:
  13. 13. 其它 Composition API
    1. 13.1. shallowReactive 与 shallowRef
    2. 13.2. readonly 与 shallowReadonly
    3. 13.3. toRaw 与 markRaw
    4. 13.4. customRef
    5. 13.5. provide 与 inject
    6. 13.6. 响应式API:工具函数
  14. 14. 新的组件
    1. 14.1. Fragment
    2. 14.2. Teleport
    3. 14.3. Suspense
  15. 15. 其他
    1. 15.1. 全局API的转移
    2. 15.2. 其他改变
请输入关键词进行搜索