快速掌握-vue3

embedded/2024/10/10 20:11:53/

是什么

vue2 的升级版, 使用 ts 重构了代码, 带来了 Composition API RFC。 类似于 react hook 的写法。

  1. ts 重构,代码可读性更强
  2. vue3.x 使用 Proxy 取代 Vue2.x 版本的 Object.defineProperty
  3. 实现了 TreeShaking (当 Javascript 项目达到一定体积时,将代码分成模块会更易于管理。但是,当这样做时,我们最终可能会导入实际上未使用的代码。Tree Shaking 是一种通过消除最终文件中未使用的代码来优化体积的方法。)
  4. 支持 hook 写法 CompositionAPI。受 ReactHook 启发
  5. 支持 jsx
  6. Vue 3 的 Template 支持多个根标签,Vue 2 不支持
  7. 对虚拟 DOM 进行了重写、对模板的编译进行了优化操作
  8. 在 Vue2.x 中具名插槽和作用域插槽分别使用 slot 和 slot-scope 来实现, 在 Vue3.0 中将 slot 和 slot-scope 进行了合并 v-slot
  9. 在 Vue 3 中对自定义指令的 API 进行了更加语义化的修改,名称和组件生命周期名称相同
  10. v-model 变更:在自定义组件上使用 v-model 时,同一组件可以同时设置多个 v-model, 开发者可以自定义 v-model 修饰符

学到什么

  1. vue3 与 vue2 的核心区别
  2. Tree-Shaking
  3. 函数 setup()
  4. 函数 ref()
  5. 函数 isRef()
  6. 函数 toRefs()
  7. 函数 reactive()
  8. 函数 computed()、watch()
  9. LifeCycle Hooks(新的生命周期)
  10. Template refs
  11. vue3 的全局配置
  12. vue3 组件模板结构
  13. 实现 自定义 Hook
  14. 组件 teleport 任意门
  15. 组件 异步组件

vue3 与 vue2 的核心区别

  1. vue3.x 将使用 Proxy 取代 Vue2.x 版本的 Object.defineProperty
  2. Object.defineProperty 只能劫持对象的属性, 而 Proxy 是直接代理对象,由于 Object.defineProperty 只能劫持对象属性,需要遍历对象的每一个属性,如果属性值也是对象,就需要递归进行深度遍历。但是 Proxy 直接代理对象,不需要遍历操作
  3. Object.defineProperty 对新增属性需要手动进行 Observe

Tree-Shaking

当 Javascript 项目达到一定体积时,将代码分成模块会更易于管理。但是,当这样做时,我们最终可能会导入实际上未使用的代码。Tree Shaking 是一种通过消除最终文件中未使用的代码来优化体积的方法。

为什么:因为 Vue 实例是作为单个对象导出的,打包器无法分辨出代码中使用了对象的哪些属性。所以,我们需要单独引用

抽离了 一部分 vue2 中的公用函数,需要单独引用。以前的全局 API 现在只能通过具名导入,这一更改会对以下 API 有影响:

  • Vue.nextTick
  • Vue.observable(用 Vue.reactive 替换)
  • Vue.version
  • Vue.compile(仅限完整版本时可用)
  • Vue.set(仅在 2.x 兼容版本中可用)
  • Vue.delete(与上同)

setup 函数

组件提供的新属性,为了使用 vue3 CompositionAPI 新特性而启用的函数,它有自己独立的生命周期

vue3 取消了 beforeCreate 、created 两个钩子函数,统一用 setup 代替

  1. props 用来接收 props 数据
  2. context 上下文对象
  3. return 返回模板中需要使用的函数
setup(props, context) {context.attrscontext.slotscontext.emitreturn {}}

ref() 函数

组件提供的新特性函数

创建一个响应式的数据对象,这个对象是响应式的,只返回一个 { value: ""} 值

import { defineComponent, ref } from "vue";
export default defineComponent({setup() {const name = ref < string > "hello";// 在js 中获取ref 中定义的值, 需要通过value属性console.log(name.value);return {name,};},
});

isRef() 函数

组件提供的新特性函数

isRef() 用来判断某个值是否为 ref() 创建出来的对象

import { defineComponent, isRef, ref } from "vue";
export default defineComponent({setup(props, context) {const name: string = "vue";const age = ref<number>(18);console.log(isRef(age)); // trueconsole.log(isRef(name)); // falsereturn {age,name,};},
});

toRefs() 函数

组件提供的新特性函数

toRefs() 函数可以将响应式对象,转换为普通的对象。只不过,这个对象上的每个属性节点,都是 ref() 类型的响应式数据

import { defineComponent, reactive, ref, toRefs } from "vue";
export default defineComponent({setup(props, context) {let state = reactive({name: "hello",});const age = ref(18);return {...toRefs(state),age,};},
});

reactive() 函数

组件提供的新特性函数

reactive() 函数接收一个普通对象,返回一个响应式的数据对象, 想要使用创建的响应式数据也很简单,创建出来之后,在 setup 中 return 出去,直接在 template 中调用即可

import { defineComponent, reactive, ref, toRefs } from "vue";
export default defineComponent({setup(props, context) {let state = reactive({name: "hello",});return state;},
});

computed()、watch() 函数

组件提供的新特性函数

computed() 函数 ,用来计算属性,返回的值是一个 ref 对象。

import { computed, defineComponent, ref } from "vue";
export default defineComponent({setup(props, context) {const age = ref<number>(18);const computedAge = computed({get: () => age.value + 1,set: (value) => age.value + value,});// 为计算属性赋值的操作,会触发 set 函数, 触发 set 函数后,age 的值会被更新age.value = 100;return {age,computedAge,};},
});

watch() 函数,用来监听属性, 当数据源变化的时候才会被执行。

import { computed, defineComponent, reactive, toRefs, watch } from "vue";
interface Person {name: string;age: number;
}
export default defineComponent({setup(props, context) {const state = reactive<Person>({ name: "vue", age: 10 });watch([() => state.age, () => state.name],([newName, newAge], [oldName, oldAge]) => {console.log(newName);console.log(newAge);console.log(oldName);console.log(oldAge);});// 修改age 时会触发watch 的回调, 打印变更前后的值, 此时需要注意, 更改其中一个值, 都会执行watch的回调state.age = 100;state.name = "vue3";return {...toRefs(state),};},
});

LifeCycle Hooks 生命周期

组件提供的新特性函数

生命周期组件中新的写法

import { set } from "lodash";
import {defineComponent,onBeforeMount,onBeforeUnmount,onBeforeUpdate,onErrorCaptured,onMounted,onUnmounted,onUpdated,
} from "vue";
export default defineComponent({setup(props, context) {onBeforeMount(() => {console.log("beformounted!");});onMounted(() => {console.log("mounted!");});onBeforeUpdate(() => {console.log("beforupdated!");});onUpdated(() => {console.log("updated!");});onBeforeUnmount(() => {console.log("beforunmounted!");});onUnmounted(() => {console.log("unmounted!");});onErrorCaptured(() => {console.log("errorCaptured!");});return {};},
});

模板 Template refs

组件提供的新特性函数

通过 refs 来回去真实 dom 元素,onMounted 中可以得到 ref 的 RefImpl 的对象, 通过.value 获取真实 dom

<template><div class="mine" ref="elmRefs"><span>hello</span></div>
</template><script lang="ts">
import { set } from "lodash";
import { defineComponent, onMounted, ref } from "vue";
export default defineComponent({setup(props, context) {// 获取真实domconst elmRefs = ref<null | HTMLElement>(null);onMounted(() => {console.log(elmRefs.value); // 得到一个 RefImpl 的对象, 通过 .value 访问到数据});return {elmRefs,};},
});
</script>

vue 的全局配置

Vue3 可以在组件用通过 getCurrentInstance() 来获取全局 globalProperties 中配置的信息

const app = Vue.createApp({});
app.config.globalProperties.$http = "axios";setup( ) {const { ctx } = getCurrentInstance();ctx.$http
}

vue3 组件模板结构

<template><div class="mine" ref="elmRefs"><span>{{ name }}</span><br /><span>{{ count }}</span><div><button @click="handleClick">测试按钮</button></div><ul><li v-for="item in list" :key="item.id">{{ item.name }}</li></ul></div>
</template><script lang="ts">
import {computed,defineComponent,getCurrentInstance,onMounted,PropType,reactive,ref,toRefs,
} from "vue";interface IState {count: 0;name: string;list: Array<object>;
}export default defineComponent({name: "demo",// 父组件传子组件参数props: {name: {type: String as PropType<null | "">,default: "vue3.x",},list: {type: Array as PropType<object[]>,default: () => [],},},components: {/// TODO 组件注册},emits: ["emits-name"], // 为了提示作用setup(props, context) {console.log(props.name);console.log(props.list);const state = reactive<IState>({name: "vue 3.0 组件",count: 0,list: [{name: "vue",id: 1,},{name: "vuex",id: 2,},],});const a = computed(() => state.name);onMounted(() => {});function handleClick() {state.count++;// 调用父组件的方法context.emit("emits-name", state.count);}return {...toRefs(state),handleClick,};},
});
</script>

实现 自定义 Hook

功能性组件可以封装成 hook, 以 use 作为前缀,和普通的函数区分

import { ref, Ref, computed } from "vue";type CountResultProps = {count: Ref<number>;multiple: Ref<number>;increase: (delta?: number) => void;decrease: (delta?: number) => void;
};export default function useCount(initValue = 1): CountResultProps {const count = ref(initValue);const increase = (delta?: number): void => {if (typeof delta !== "undefined") {count.value += delta;} else {count.value += 1;}};const multiple = computed(() => count.value * 2);const decrease = (delta?: number): void => {if (typeof delta !== "undefined") {count.value -= delta;} else {count.value -= 1;}};return {count,multiple,increase,decrease,};
}

使用 hook

<template><p>count: {{ count }}</p><p>倍数: {{ multiple }}</p><div><button @click="increase()">加1</button><button @click="decrease()">减一</button></div>
</template><script lang="ts">
import useCount from "../hooks/useCount";setup() {const { count, multiple, increase, decrease } = useCount(10);return {count,multiple,increase,decrease,};},
</script>

组件 teleport 任意门

目的: 即希望继续在组件内部使用 Dialog, 又希望渲染的 DOM 结构不嵌套在组件的 DOM 中

场景: 弹框

我们可以用<Teleport>包裹 Dialog, 此时就建立了一个传送门,可以将 Dialog 渲染的内容传送到任何指定的地方。使用 teleport 组件,通过 to 属性,指定该组件渲染的位置与 <div id="app"></div> 同级,也就是在 body 下,但是 Dialog 的状态 dialogVisible 又是完全由内部 Vue 组件控制.

<body><div id="app"></div><div id="dialog"></div>
</body>
// Dialog.vue
<template><teleport to="#dialog"><div class="dialog"><div class="dialog_wrapper"><div class="dialog_header" v-if="title"><slot name="header"><span>{{ title }}</span></slot></div></div><div class="dialog_content"><slot></slot></div><div class="dialog_footer"><slot name="footer"></slot></div></div></teleport>
</template>// Footer.vue 子组件<div class="footer">...<Dialog v-if="dialogVisible"></Dialog>
</div>

组件 异步组件

Vue3 中 使用 defineAsyncComponent 定义异步组件,配置选项 component 替换为 loader ,Loader 函数本身不再接收 resolve 和 reject 参数,且必须返回一个 Promise。

<template><!-- 异步组件的使用 --><AsyncPage />
</template><script>import { defineAsyncComponent } from "vue";export default {components: {// 无配置项异步组件AsyncPage: defineAsyncComponent(() => import("./NextPage.vue")),// 有配置项异步组件AsyncPageWithOptions: defineAsyncComponent({loader: () => import(".NextPage.vue"),delay: 200,timeout: 3000,errorComponent: () => import("./ErrorComponent.vue"),loadingComponent: () => import("./LoadingComponent.vue"),}),},};
</script>

参考

  1. vue3 官网 https://v3.vuejs.org/
  2. 构建 vite https://github.com/vitejs/vite
  3. vue3 源码 https://github.com/vuejs/vue-next
  4. vue-cli https://cli.vuejs.org/
  5. vue-router https://github.com/vuejs/vue-router-next
最后编辑于:2024-09-24 21:09:17


喜欢的朋友记得点赞、收藏、关注哦!!!


http://www.ppmy.cn/embedded/124618.html

相关文章

Python 从入门到实战33(使用MySQL)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;通过熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 上篇文章我们讨论了数据库编程接口操作的相关知识。今天我们将学习…

探索Python文本处理的新境界:textwrap库揭秘

文章目录 **探索Python文本处理的新境界&#xff1a;textwrap库揭秘**一、背景介绍二、textwrap库是什么&#xff1f;三、如何安装textwrap库&#xff1f;四、简单函数使用方法4.1 wrap()4.2 fill()4.3 shorten()4.4 dedent()4.5 indent() 五、实际应用场景5.1 格式化日志输出5…

MATLAB计算与建模常见函数:2.回归模型

回归模型 回归分析(regressionanalysis) 是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法&#xff1b;在大数据分析中&#xff0c;回归分析是一种预测性的建模技术&#xff0c;它研究的是因变量&#xff08;目标&#xff09;和自变量&#xff08;预测器&…

设计模式-生成器模式/建造者模式Builder

构建起模式&#xff1a;将一个复杂类的表示与其构造分离&#xff0c;使得相同的构建过程能够得出不同的表示。&#xff08;建造者其实和工厂模式差不多&#xff09; 详细的UML类图 图文说明&#xff1a;距离相同的构建过程 得出不同的展示。此时就用两个类&#xff08;文本生成…

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(2)Keras

文章目录 前言一、Keras二、使用Kears 估计回归问题的神经网络1. 载入、处理数据2. 数据预处理&#xff1a;归一化3. 设定一系列随机数种子4. 定义了一个简单的深度神经网络5. 训练模型6. 查看训练结果7. 使用最优轮数&#xff08;index1&#xff09;重新估计 此神经网络模型8.…

第一弹:C++ 的基本知识概述

文章目录 知识点 1&#xff1a;C 的概述1. C的特征2. C 程序的编辑、编译和执行3. 第一个 C 源程序4. 面向对象程序设计思想4.1 面向对象程序设计思想初始4.2 面向对象程序设计思想的核心 知识点 2&#xff1a;C 对 C 的扩展1. 作用域访问运算符 ::1.1 全局变量和局部变量1.2 作…

Python从0到100(六十):机器学习-模型选择与交叉验证

前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、 计算机视觉、机器学习、神经网络以及人工智能…

通信工程学习:什么是TCP传输控制协议

TCP&#xff1a;传输控制协议 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是因特网协议套件中最重要的协议之一&#xff0c;它为应用程序提供了可靠、面向连接的通信服务。以下是TCP协议的详细解释&#xff1a; 一、TCP传输控制协议的…