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

举报
空城机 发表于 2022/07/10 19:04:08 2022/07/10
【摘要】 在之前的学习中,对 vue3 和 vite 做了一下简单的了解。也知道了 vue3,相较于 vue2,对 typescript 的兼容更好了,本文中主要对 TS 模块声明,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, 同样也会保持响应式链接,修改响应式数据会影响以前的数据;数据改变,界面不自动更新

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。