Vue 3 开发文档

本文深入探讨了Vue 3的Composition API,包括Vite的介绍、setup函数、生命周期钩子、响应式数据声明等。重点讨论了Composition API如何解决组件逻辑共享和重用的问题,以及ref和reactive函数在创建响应式数据中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

yarn global add @vue/cli@next

or

npm install -g @vue/cli@next

如果想要在现有的项目中(Vue 2.x),升级构建工具,则需要执行以下代码

vue upgrade --next

Vite

Vite 是一个想要用来代替 webpackWeb 开发构建工具,也是官方推荐使用的构建工具,使用 vite 将脱离 webpack

// ----------npm----------

npm init vite-app

cd

npm install

npm run dev

// ----------yarn----------

yarn create vite-app

cd

yarn

yarn dev

Composition API


简介

为什么会有 Composition API

创建Vue组件使我们能够将接口的可重复部分及其功能提取到可重用的代码段中。就维护性和灵活性而言,仅此一项就可以使我们的应用程序发展得相当远。

但是,经过大量的开发经验证明,仅凭这一项可能还不够,特别是当你的应用程序变得非常大时。

想象一下数百个组件的项目,在处理如此大的应用程序时,共享和重用代码变得尤为重要。

摘要自:https://v3.vuejs.org/guide/composition-api-introduction.html#why-composition-api

但是因为 Vue 2.x 中,以 组件 为最小颗粒的原因(PS:mixin 虽然可以达到复用的效果,但是它依然缺少独立性。比如:命名冲突、隐式依赖的问题),导致组件中的逻辑无法被进行 共享重用

Composition API 概念

Composition API组合式 API) 是一个概念,而非具体的实现。

在组件中,实际使用 Composition API 的地方,是 setup 函数。在它内部,我们可以描述一个组件所需要的 所有逻辑

setup

简介

setup 函数是Composition API 的入口函数,也是它的核心函数。

但是要注意:setup 函数执行时,尚未创建组件实例,所以 this 中没有任何内容。这意味着,除了props,你将无法访问通过 this 来访问组件中声明的任何属性、本地状态、计算属性、方法。

参数

setup 函数有两个参数:

  1. {Data} props

  2. props 是响应式的

  3. 由于props是反应性的,你不能使用ES6解构,详见 对象的响应式

  4. {SetupContext} context

  5. context 是普通的 js 对象,所以他不是响应式的

  6. context 下有三个属性:

  7. attrs:包含父组件属性绑定、未识别出的为组件属性或自定义事件的事件

  8. slots:插槽

  9. emit:通知(发出的事件)

下面是官方的示例代码:

// Data 为 key:value 结构的对象

interface Data {

}

// context 为上下文,包含:

// attrs:包含父组件属性绑定、未识别出的为组件属性或自定义事件的事件

// slots:插槽

// emit:通知

interface SetupContext {

attrs: Data

slots: Slots

emit: (event: string, …args: unknown[]) => void

}

function setup(props: Data, context: SetupContext): Data

可访问的组件属性

setup被执行时,该组件实例尚未建立。如此一来,您将只能访问以下属性:

  • props

  • attrs

  • slots

  • emit

换句话说,您将无权访问以下组件选项:

  • data

  • computed

  • methods

模板使用 setup 中的数据

如果setup返回对象,则可以在组件的模板中访问对象的属性(注意代码中的备注):

{{ readersNumber }} {{ book.title }}
渲染功能的实现

setup 还可以返回一个渲染函数,该函数可以直接使用在同一作用域中(setup 函数中)声明的反应状态 :

import { h, ref, reactive } from ‘vue’

export default {

setup() {

const readersNumber = ref(0)

const book = reactive({ title: ‘Vue 3 Guide’ })

// Please note that we need to explicitly expose ref value here

return () => h(‘div’, [readersNumber.value, book.title])

}

}

this 指向问题

setup 函数中,thisundefined 而不是 组件的引用。因为 setup 函数执行时,尚未创建组件实例。所以 thissetup 中无法正常使用。

setup 函数和其他的 Options API 一起使用时,可能会出现无法预知的错误,所以一定要谨慎。

生命周期钩子

setup 中,可以通过 onX 的方式注册 生命周期钩子

import { onMounted, onUpdated, onUnmounted } from ‘vue’

const MyComponent = {

setup() {

onMounted(() => {

console.log(‘mounted!’)

})

onUpdated(() => {

console.log(‘updated!’)

})

onUnmounted(() => {

console.log(‘unmounted!’)

})

}

}

Options API(Vue 2.x) 生命周期选项和 Composition API(Vue 3.x) 之间的映射

  • beforeCreate ->使用 setup()

  • created ->使用 setup()

  • beforeMount -> onBeforeMount

  • mounted -> onMounted

  • beforeUpdate -> onBeforeUpdate

  • updated -> onUpdated

  • beforeUnmount -> onBeforeUnmount

  • unmounted -> onUnmounted

  • errorCaptured -> onErrorCaptured

  • renderTracked -> onRenderTracked

  • renderTriggered -> onRenderTriggered

提供 provide / 注入 inject

首先必须要明确:提供 provide / 注入 inject 的功能都只能在 setup 函数中进行使用。

如果你希望在 父组件 中提供一个值,然后在 子组件 中可以使用。那么你就应该考虑 提供 provide / 注入 inject 的功能。

// 父组件

setup() {

// 为子组件提供一个值,并且这个值是响应式的(ref)

// 则代表:子组件可以修改该值(book.value),并且会 响应式的 作用于父组件的变量中

let book = ref(‘父组件的book’);

// 为子组件提供一个值,并且这个值不是响应式的

// 则代表:子组件获取到了 非响应式的 数据。

// 此时:子组件可以通过 ref(inject(‘book’, ‘默认值’)) 的方式,把该数据变为 响应式的 ,但是要注意,此时的响应式仅在 子组件中生效

let book = ‘父组件的book’;

provide(‘book’, book);

return {

book,

};

},

// 子组件

setup () {

// 利用 inject 函数,获取父组件提供的值

let book = inject(‘book’, ‘默认值’);

// 利用 inject 函数,获取父组件提供的值,同时把它变为响应式的。但是要注意,此时的响应式仅在 子组件中生效

let book = ref(inject(‘book’, ‘默认值’))

}

新的响应式


代理对象

当我们把 JavaScript 对象作为 data 选项传递给 Vue 实例的时候,Vue 会遍历对象的所有属性,并且会把它们转化成带有 gettersetter 函数的 Proxies(代理对象)

同时为了兼顾低版本的浏览器,对于较久的版本,Vue 依然使用 Object.defineProperty 来进行支持。

两者之间在使用中并没有区别,只不过 代理对象 会提供更好的性能。

响应式数据的声明 - reactive 函数

想要在 setup函数中 创建响应式数据,可以使用 reactive方法(注意:需要主动导入 reactive

Vue 3

<button @click=“state.count++”>count is: {{ state.count }}

注意:Vue 3 中并没有取消 data 声明,也就是说,我们依然可以使用 data 函数来创建响应式数据。以下两种写法在响应式效果 中等效

// setup() {

// const state = reactive({

// count: 0,

// });

// return {

// state,

// };

// },

// 效果等效

data() {

return {

state: {

count: 0,

},

};

},

将一个非响应式数据转化为响应式数据 - ref 函数

Vue 3 对 ref 函数进行了改变,使 ref 具备了两种能力:

  1. 使用 ref 获取 元素 或 组件实例

  2. 可以把一个非响应式的数据改变为响应式的

我们在这里探讨的就是 ref 函数的第二个能力:

Vue 3

<button @click=“count++”>count is: {{ count }}

以上三种方式,貌似可以达到同样的效果。

那么 ref 的作用是什么呢?再来回顾一下:ref 函数可以将一个非响应式数据转化为响应式数据。即:当数据发生了变化的时候,视图也理应发生变化。我们来看下面的代码:

setup() {

// ----- 利用 setup 函数返回 ------

let count = 0;

setTimeout(() => {

// 视图并没有发生变化

count = 1;

}, 1000);

return {

count,

};

// ----- 利用 reactive 函数 ------

et state = reactive({

count: 0,

});

setTimeout(() => {

// 视图并没有发生变化

state.count = 1;

}, 1000);

return {

count: state.count,

};

// ----- 利用 ref 函数 ------

let count = ref(0);

setTimeout(() => {

// 访问 count 的值,需要使用 value 属性

// 注意:在模板中,我们不需要手动写入 value

// 视图发生了变化

count.value = 1;

}, 1000);

return {

count,

};

},

在上面的代码中,我们通过 setTimeout 延迟 1 秒钟之后改变数据源 count 的值,从结果中,我们可以发现,只有被 ref 函数声明的 count 才会直接影响视图的变化。

对象的响应式

通常情况下,我们希望利用 解构赋值 的方式来获取到响应式数据:

Vue 3

<button @click=“count++”>count is: {{ count }}

但是很遗憾,这种方式将会让 count 失去响应性

如果我们想要解决这个问题,那么需要借助一个函数 toRefs。同样的,我们需要先 导入 这个函数。

// 不要忘记,我们需要导入 toRefs

import { toRefs } from ‘vue’;

let state = reactive({

count: 0,

});

// 借助 toRefs 函数,让数据保持响应性

let { count } = toRefs(state);

setInterval(() => {

// 同样需要是使用 value 来访问到数据源

count.value++;

}, 1000);

return {

count,

};

只读的响应式数据

有时我们希望 数据为响应式 的同时,该数据不被其他的组件所修改 (即:我们想要其他组件 享受 响应数据(refreactive )的变化,同时也想要防止其他的组件修改响应式数据),那么我们需要给其他组件 只读的响应式数据 - readonly

<button @click=“state.count++”>count is: {{ state.count }}

<button @click=“readonlyState.count++”>count is: {{ readonlyState.count }}

这样我们就获得了一个只读的响应式数据 readonlyState 和它的源数据 state 。如果我们想要修改 readonlyState 的值,那么唯一的方式是 修改state

对于 readonly 来说,源数据的变化会响应式的作用于 readonly

计算属性与侦听器


计算属性

基本用法

Vue 计划使用 computed 函数 来定义 计算属性 (这并不代表 Options API 被完全丢弃),看下面的示例:

{{ comStr }}

set 和 get

computed 函数 包含了 getset 方法:

const count = ref(1)

// 此代码等于使用了 getter 函数

const plusOne = computed(() => count.value++)

// 当我们获取 plusOne 的值时,等于调用了 get

console.log(plusOne.value) // 2

// 但是因为没有实现 setter 函数,所以无法设置新值

// err:setter is not a function

plusOne.value++

后话

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

对于面试,说几句个人观点。

面试,说到底是一种考试。正如我们一直批判应试教育脱离教育的本质,为了面试学习技术也脱离了技术的初心。但考试对于人才选拔的有效性是毋庸置疑的,几千年来一直如此。除非你有实力向公司证明你足够优秀,否则,还是得乖乖准备面试。这也并不妨碍你在通过面试之后按自己的方式学习。
其实在面试准备阶段,个人的收获是很大的,我也认为这是一种不错的学习方式。首先,面试问题大部分基础而且深入,这些是平时工作的基础。就好像我们之前一直不明白学习语文的意义,但它的意义就在每天的谈话间。

所谓面试造火箭,工作拧螺丝。面试往往有更高的要求,也迫使我们更专心更深入地去学习一些知识,也何尝不是一种好事。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值