Vue3 变量的访问控制与实现最佳化

更新日期: 2024-03-18阅读: 134标签: Vue3

一些参考进行访问的时候的规划,还有官方案例的深度解析以及vue的响应式进阶api的使用,看完后可能会让你有些想法。

在编写 Vue 要声明具有响应式特性的数据的时候,我们不妨用来ref定义数据,然后可以透过.value来直接修改它。

// 宣告一個具有響應式的資料
const name = ref("");

// 更改變數的 value
name.value = "mike"

当我们今天遇到在子组件去修改父组件的状态需要的时候,除了使用emit外部,也可以利用类似于单向数据流的方式,定义一个状态的函数然后用 props 传递下去。

单向数据流其实就是 react 中的 Lifting State Up ( 状态提升 ),概念是一样的。

关于 Emit 与单向数据流的一些细节在参加铁人赛之前的时候我有针对这个主题进行一些介绍,可以搭配观看。https://ithelp.ithome.com.tw/articles/10273655

<script setup>
const isOpen = ref(false);
const Toggle = () => isOpen.value = !isOpen.value;
</script>

<template>
<Header :Toggle="Toggle" />
<Nav :Toggle="Toggle" :Toggle="Toggle" />
</template>

其中我相信大家应该都没有什么棘手的问题,接下来我要来探讨一下变数访问控制这件事。


封装(Encapsulation)

在大型架构在开发的时候,我们很常会使用封装的概念来编写我们的程序代码,举个最简单的例子来说,我们定义了一个变数,但是我们要修改这个变数不是采用直接的方式=来进行设置,而是利用隐藏功能来进行修改,中间的细节和过程,只穿透功能(介面)来操作变数。

// 宣告變數
let a = 1;

// 宣告 set function
const setCount = (int) => {
a = int;
}

// 使用 set function 修改變數
setCount(4);

在上面提到的例子中,通过函式setCount来修改变量count的值,而不是直接操作变量,就是一种封装的做法,这样可以控制变量设置的过程,例如加入额外的检查或逻辑。

然而这种做法大量的被现代前端框架的React运用的淋漓尽致,当今天使用useState的时候,就可以有值以及set函数可以使用。

官方文件:https ://react.dev/reference/react/useState
import { useState } from 'react';

function MyComponent() {
const [age, setAge] = useState(28);
const [name, setName] = useState('Taylor');
const [address, setAddress] = useState('Taiwan');
}

我们可以不用去再另外定义设置函数,身为一个 Vue 的开发者,我觉得 React 在 useState 这方面真的做的很。在小型专案上面来说不错,我直接定义然后用去修改真的是ref超.value方便修改,但是当你今天需要发出或者传递要传递 props 的时候你还是需要定义 set 函数,这个时候你去的父层组件在可能会ref同时存在.value,set function尤其你的专案或者组件开始变大,相对话说会乱了一点。

举个简单的例子,我有一个activeIdx状态是需要查看网址的查询参数来更改的,但是我同时会在下面开始进入网页的时候以及网址有波动的时候去改变状态,从的例子可以activeIdx看到话说对于设置一个状态来说有太多的地方了,如果一接手别人的代码看到这样子会有一种别扭的感觉。

const route = useRoute();

const activeIdx = ref(0);

const setActiveIdx = (idx) => {
activeIdx.value = idx;
};

watch(route, (newRoute) => {
activeIdx.value = newRoute.query.activeId; // 這邊去修改
});

onMounted(()=> {
setActiveIdx(route.query.activeId) // 這邊去修改
})


时间终于造成了问题?

很多时候是因为写代码的过程演进过来的,首先一开始可能并没有定义的setActiveIdx必要,只需要交叉.value去设置就好,然后当需求越做越大的时候开始需要提交道具你可能就去定义设置函数,后面又需要在父层一开始进去去设定activeIdx状态,随着时间增加一个接一个,然后时间又很赶,没时间整理代码就会出现这样的情况。


统一你的状态访问方式

现在在Vue的中大型开发上面,会有composables(消耗逻辑处理)以及pinia(全域状态管理)的使用,针对这些封装的我们的逻辑也会有状态以及提供set function来去操作,虽然有些东西并不强制一定要提供这些设置功能,但是对于引入这些抽出的状态来说,利用封装的概念提供设置功能是可以避免跟踪组件的状态冲突以及增加代码的唯一性,重要的是可以有更好的追踪的方案流动。

所以我现在基本上在定义ref此类的响应方式资料的时候,只要在规划上面会拆组件或者稍微复杂一些,我可能会手动增加一个设置功能,事先准备,来避免我前面提到的改变状态的地方过多的问题,而且未来增加新的需求的时候你也可以直接透过设定功能来更改值,方便的很。

const username = ref("");

const setUsername = (name) => username.value = name;


问题连接就出现了

如果我有很多个ref我不是就需要很多设定功能……

const age = ref(28);
const userName = ref('Taylor');
const address = ref('Taiwan');
const setAge = (num) => age.value = num;
const setUserName = (name) => userName.value = name;
const setAddress = (addr) => address.value = addr;

这样虽然解决了前面提到的问题,但是也出现了每次都要定义 set 函数的麻烦,代码也变得多,所以有没有一种办法是可以把 React 的 useState 放在 Vue 里面实现呢?

const [state, setState] = useState(initialState)

因此接下来为了实现 React 的 useState 的语法,我们要编写一个可组合项

先打个预防针,以下部分代码可能会使部分Vue用户身体不适,请尽速离开此页面。

我们可以先添加 composables/ useState.js的文件,然后添加以下的代码

import { shallowRef } from "vue";

export function useState(baseState) {
const state = shallowRef(baseState);
const update = (newValue) => {
state.value = newValue;
};
return [state, update];
}

这么大我们就可以在开发的时候使用跟React一样的方式来定义数据。

<script setup>
import { useState } from "./composables/useState.js";
const [name, setName] = useState("mike");
const [info, setInfo] = useState({
name: "mike",
age: 12,
});
</script>

<template>
<h2>name: {{ name }}</h2>
<pre>info: {{ info }}</pre>

<input type="text" v-model="name" />

<button @click="setName('jacky')">set name</button>
<button @click="setInfo({ name: 'andy', age: 20 })">set info</button>
</template>

这样的一种处理方式就可以减少每次在定义ref的时候都要重新写一套函数,造成代码会很多很杂的问题,而且也不会失去响应式的特性!

范例给大家参考!https://codesandbox.io/p/devbox/vue3-usestate-w297jd


为什么不是参考?什么是shallowRef?

shallowRef是一个 Vue 的响应式进阶 API,它是ref浅层的作用层,它和ref不同,shallowRef内部的值并转换不会生成响应式,只有针对.value的集合才会是响应式,所以第一层的部分。

shallowRef常用于大型数据结构的优化与外部的状态管理系统集成。

const state = shallowRef({ count: 1 })

// 不會觸發更新
state.value.count = 2

// 會觸發更新
state.value = { count: 2 }

当我们使用useState之后,就不能直接针对对象去设置值,需要将具体的对象加上新的值一起写入

const [info, setInfo] = useState({
name: "mike",
age: 12,
});

// 把原本的物件加上新的值一起寫入
setInfo({
...info,
address: addr,
});

基本上就相当于直接替换整个对象一样,所以草莓就不需要使用ref来增加无所谓的可能消耗。

ref的响应方式是深度的,虽然这样很有趣,但是在数据量庞大的时候,深度响应性也会导致不小的履行负载,因为每个属性访问都会触发代理的追踪。但是这种负载通常只有在处理超大规模数据或体系很深的对象时,比如一次渲染需要100,000+个属性时,会变得比较明显。

所以 Vue 提供了一种解决方案,跨越使用shallowRef并shallowReactive来绕过深度响应。shallow API 的状态只在第一层是响应方式的,对所有深度的对象不会做任何处理。这使得对深度属性的访问变得更快,但是我们必须将所有深度对象的属性视为不可变(不可变),并且只能使用替换整个对象来触发更新。

来源:https://medium.com/i-am-mike/vue3-變數的存取控制與效能最佳化-fdd45a9789ac

链接: https://www.fly63.com/article/detial/12685

vue3.x 新特性 - CompositionAPI

安装 vue-cli3,在使用任何 @vue/composition-api 提供的能力前,必须先通过 Vue.use() 进行安装,安装插件后,您就可以使用新的 Composition API 来开发组件了。

Vue3数据响应系统

Vue3 就是基于 Proxy 对其数据响应系统进行了重写,现在这部分可以作为独立的模块配合其他框架使用。数据响应可分为三个阶段: 初始化阶段 --> 依赖收集阶段 --> 数据响应阶段

快速进阶Vue3.0

在2019.10.5日发布了Vue3.0预览版源码,但是预计最早需要等到 2020 年第一季度才有可能发布 3.0 正式版。新版Vue 3.0计划并已实现的主要架构改进和新功能:

Vue 3 对 Web 应用性能的改进

有关即将发布的 Vue.js 的第 3 个主要版本的信息越来越多。通过下面的讨论,虽然还不能完全确定其所有内容,但是我们可以放心地认为,它将是对当前版本(已经非常出色)的巨大改进。 Vue 团队在改进框架 API 方面做得非常出色

Vue3 中令人兴奋的新功能

用新的 Vue 3 编写的程序效果会很好,但性能并不是最重要的部分。对开发人员而言,最重要的是新版本将会怎样影响我们编写代码的方式。如你所料,Vue 3 带来了许多令人兴奋的新功能。值得庆幸的是

200 行从零实现 vue3

emmm 用半天时间捋顺了 vue3 的源码,再用半天时间写了个 mini 版……我觉得我也是没谁了,vue3 的源码未来一定会烂大街的,我们越早的去复现它,就……emm可以越早的装逼hhh

从 Proxy 到 Vue 源码,深入理解 Vue 3.0 响应系统

10 月 5 日,尤雨溪在 GitHub 开放了 Vue 3.0 处于 pre-alpha 状态的源码,这次 Vue 3.0 Updates 版本的更新,将带来五项重大改进:速度体积、可维护性、面向原生、易用性

Vue 的数据响应式(Vue2 及 Vue3)

从一开始使用 Vue 时,对于之前的 jq 开发而言,一个很大的区别就是基本不用手动操作 dom,data 中声明的数据状态改变后会自动重新渲染相关的 dom。换句话说就是 Vue 自己知道哪个数据状态发生了变化及哪里有用到这个数据需要随之修改。

在Vue2与Vue3中构建相同的组件

Vue 开发团队终于在今天发布了 3.0-beta.1 版本,也就是测试版。通常来说,从测试版到正式版,只会修复 bug,不会引入新功能,或者删改老功能。所以,如果你对新版本非常感兴趣,或者有新项目即将上马,不妨尝试一下新版本

Vue3中的Vue Router初探

对于大多数单页应用程序而言,管理路由是一项必不可少的功能。随着新版本的Vue Router处于Alpha阶段,我们已经可以开始查看下一个版本的Vue中它是如何工作的。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!