写点什么

不习惯的 Vue3 起步二 の alias 别名、ref 和 reactive

作者:空城机
  • 2022 年 7 月 10 日
  • 本文字数:2292 字

    阅读完需:约 8 分钟

不习惯的Vue3起步二 の alias别名、ref和reactive

在之前的学习中,对 vue3 和 vite 做了一下简单的了解。也知道了 vue3,相较于 vue2,对typescript的支持更加好了。所以直接从 ts+vue3 一起来吧。(之前我对typescript基础也有过学习,忘记也可以翻看资料《typescript系列笔记》

vue3 + ts 项目

创建的还是vite项目,之前没有使用 ts,所以创建项目命令: yarn create vite first-vite-demo --template vue。 现在如果要在项目中添加 ts,只需要在命令最后加上-ts: yarn create vite demo-name --template vue-ts


这样创建出来的项目,main.js 也已经变成了 main.ts


项目结构:


然后现在的.vue组件中,<script>上需要添加lang="ts


因为使用命令创建完项目后,会自动生成tsconfig.json。不过这里关于tsconfig.json配置也可以根据自己需求调整,可以参考


TS 模块声明

在 ts 中,有类型声明的特性,在 vue3+ts 项目中,会看到一个env.d.ts文件,此文件中声明了*.vue

declare module '*.vue' {  import type { DefineComponent } from 'vue'  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types  const component: DefineComponent<{}, {}, any>  export default component}
复制代码


如果将其注释掉,会发现main.ts中出现红色波浪线报错:


resolve.alias 别名

在引用文件时,可以使用相对路径的方式,但是这样嵌套的页面非常复杂,有可能会造成多个层级../../../这种引用情况,所以有时候可以通过配置resolve.alias别名来进行缓解。


vite.config.ts文件中,引入path中的resolve,然后在defineConfig写入配置的相对路径:

import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import { resolve } from 'path';
// https://vitejs.dev/config/export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': resolve(__dirname, './src') } }})
复制代码


这样调用路径时就可以使用@来引入


PS:如果这样在 ts 项目中还未成功,可以在tsconfig.jsoncompilerOptions进行配置

"baseUrl": ".",
"paths": {
  "@/*":["src/*"]
}

ref 和 reactive

ref: 接受一个内部值并返回一个响应式且可变的 ref 对象,ref底层其实还是reactive,所以当运行时系统会自动根据传入的ref转换成reactive


这是为了实现数据响应式,如果单纯对变量定义为一个数据,是不会在template中实现数据响应式变动的。


比如:

<template>{{ count }}</template>
<script setup lang="ts"> import { ref, reactive } from "vue"; let count = 10
setInterval(()=>{ count++; }, 1000)</script>
复制代码


最终界面上依旧是 10,setInterval 产生的变动并没有实时更新。


而如果 count 做 ref 的定义,那么界面上数据就会实时更新

<script setup lang="ts">    import { ref, reactive } from "vue";    // ref就是某个元素,简单数据类型,reactive对象    let count = ref(10)
setInterval(()=>{ count.value++; }, 1000)</script>
复制代码


PS: 在 vue 中使用 ref 的值不用通过 value 获取,在 js 中使用 ref 的值必须通过 value 获取


如果想要像以前 Vue2 一样,通过 refs.refname 获取元素,也要稍作改变


<template>    <div class="box" ref="box"></div></template>
<script setup lang="ts"> import { ref, reactive, onMounted } from "vue"; // 名称要与节点上ref名称一致 let box = ref(null)
onMounted(()=>{ // setup执行时机比mounted早,此时界面dom还没形成 console.log(box.value) })</script>
复制代码



reactive是用来定义更复杂的数据类型的,以下是 reactive 的具体示例

<template>    <div class="box" ref="box">        {{ users[0] }}    </div></template>
<script setup lang="ts"> import { ref, reactive, onMounted, toRefs } from "vue"; interface personInfo { name: string, age: number, hobby: ()=>void }
let users: personInfo[] = reactive([ { name: '张三', age: 18, hobby: ()=>{ console.log('打李四') } } ]) let refUsers = toRefs(users); setInterval(()=>{ refUsers[0].value.age++; },1000)</script>
复制代码


效果:


以上是使用reactive定义对象,实际上reactive也可以包裹 ref,比如:

<template>    <div class="box" ref="box">        {{ count }}    </div></template>
<script setup lang="ts">import { ref, reactive, onMounted, toRefs } from "vue"; let count = ref(10) let countRef = reactive({ count }) console.log(countRef) setInterval(()=>{ countRef.count++; },1000)</script>
复制代码

ref 和 reactive 区别

  • reactive 接受入参必须是对象形式,而 ref 可以是对象形式,也可以是一个单值。

  • 读取/赋值不一样,ref 必须从.value 属性中读取值

  • ref 存在异步问题

toRef 和 toRefs

toRefs 只会为源对象中包含的 property 生成 ref, 将对象转换为普通对象,且不丢失对源对象的响应式链接,即修改源对象属性值,生成的新的普通对象的对应属性值(ref)也会修改,反之亦然。更新响应式数据的时候不会更新界面,用于批量设置多个数据为响应式


toRef 为特定的 property 创建 ref, 同样也会保持响应式链接,修改响应式数据会影响以前的数据;数据改变,界面不自动更新

发布于: 刚刚阅读数: 6
用户头像

空城机

关注

曾经沧海难为水,只是当时已惘然 2021.03.22 加入

业余作者,在线水文 主要干前端的活,业余会学学python 欢迎各位关注,互相学习,互相进步

评论

发布
暂无评论
不习惯的Vue3起步二 の alias别名、ref和reactive_Vue3_空城机_InfoQ写作社区