ts+vu3+setup+volar

微软推出的
    typescript>ES6>javascript
    运行的时候,ts 编译成javascript
    静态类型的语言
        强类型
        遵循ES6
        编译器严谨的语法检查
    vue,react,angular,小程序都推荐用ts
    ts默认文件后缀名.ts
Vue3+TS+setup+volar
<script lang="ts" setup>
定义变量
    字符串
        const str = ref<string>("abc")
        const str = ref("abc")
根据值类型自动判断改类型变量是什么
    数字
        const count = ref<number>(10)
const count = ref(10)
    布尔值
        const flag = ref<boolen>(true)
const flag = ref(true)
    函数
        function add(n1:string,n2:number):void{
}
    接口
        定义接口
interface Iuser = {
name:string,
age:number|string
}
        const user = reactive<Iuser>({
    name:"mumu",
   age:18
})
    在setup中获取props
        import{defineProps} from 'vue'
        intervace Iprops = {min:number,max:number}
        const props =defineProps<Iprops>()

前期准备

  1. 使用vue-cli创建一个 vue3 + TS 的项目

    相关可去 cli.vuejs.org/zh/guide/[1] 查看

  2. vscode禁用 Vetur,下载Volar

相关下载以及说明可去 marketplace.visualstudio.com/items?itemN…[2] 查看

注意:vue3 不支持 ie 全系(包括 ie11),因为 ie 并不支持 proxy api。若你想使用 vue3 相关语法,请等待 vue2.7。预期将在 2021 q3 或者 q4 发布 vue2.7,详情见:github.com/vuejs/rfcs/…[3]

什么是 setup sugar

在单文件组件(SFC)中引入一个新的 <script> 类型 setup。它向模板公开了所有的顶层绑定。

未使用setup sugar

 
  1. <template>

  2.   <Foo :count="count" @click="inc" />

  3. </template>

  4. <script>

  5. import Foo from './Foo.vue'

  6. import { ref } from 'vue'

  7. export default {

  8.   setup() {

  9.     const count = ref(1)

  10.     const inc = () => { count.value++ }

  11.     return {

  12.       Foo,

  13.       count,

  14.       inc

  15.     }

  16.   }

  17. }

  18. </script>

使用了setup sugar

 
  1. <template>

  2.   <Foo :count="count" @click="inc" />

  3. </template>

  4. <script setup>

  5. // 导入的组件也可直接可用于模板(指令同理,同样会被自动注册)

  6. import Foo from './Foo.vue'

  7. import { ref } from 'vue'

  8. // 书写组合式 api 就像在正常的 setup 中一般,但是不需要进行手动地进行 return

  9. const count = ref(0)

  10. const inc = () => { count.value++ }

  11. </script>

你可以在 github.com/vuejs/rfcs/…[4] 以及github.com/vuejs/rfcs/…[5] 看到有关 setup sugar 和 ref sugar有关更多的讨论。个人不喜欢ref sugar,个人认为.value的写法比较好理解,结合Volar的帮助提示,已经没有多少的心智负担。

vue3 组合式写法是否会产生更多问题

目前网络上很多人反应使用组合式 api 反而显得代码更加乱了。那么从vue2options apivue3composition api写法,究竟会获得什么好处呢?

  1. 逻辑耦合度更高:在options api中如何一个功能我们需要用到 data+method+watch...等更多 api,一段代码无法合并在一起,我们在阅读一段逻辑需要进行反复上下移动进行观看。而composition api就解决了这个问题。

  2. 功能抽离:得益于函数式编程,一个功能逻辑我们可以封装到一个 hook 中,我们直接导入hook,运行方法,即可。

缺点:从options api切换到composition api最大的问题无异于最大的问题就是没有强制的代码分区,如果书写的人没有很好的代码习惯,那么后续的人将会看的十分难受。目前我是这么解决的:

  • 自我代码分区并且尽量抽离方法(写好注释),分区如下:

  1. 相关引入

  2. 响应式数据、props、emit 定义

  3. 生命周期以及 watch 书写

  4. 方法定义

  5. 方法、属性暴露

image.png

  • 组件抽离:将页面拆成两个文件夹,一个为 views,一个为 components。views 和 components 文件夹下有各自的文件。views 文件夹中为页面入口,掌管数据,而 components 则为页面中一些组件抽离。如果是公共组件,再抽离到 components 文件夹下其他位置。

  • hook 抽离:尽可能将逻辑抽离,并不一定要进行复用。

  • setup 衍生出的新的 api

    define 编译器宏(compiler macros )

    以 define开头的 api 都为编译器宏(compiler macros )api,只能在 <script setup> 中使用。它们不需要被导入,并且在处理 <script setup> 时被编译掉。

    注意:define类 api 必须直接在 setup 中外层进行使用,你无法将其放在方法中。

    注意:define类 api 虽然不用导入,但是这一点和 TS 兼容不太好,如果不引入会提示 undefined,如果进行了引入,会有 warning 提示。

    注意:define类 api虽然目前都可以使用 TS 类型声明,但是你无法导入一个 interface 或者 type 进行类型声明(直接在文件中声明是可以的),因为这样会报错。猜测这一点是和 define编译器宏有关,可能后期会被修复。

    1. defineProps:这个 api 很好理解,就是定义 props 相关信息。

      基础用法:

     
      
    1. defineProps({

    2.   name: {

    3.     type: String,

    4.     required: false,

    5.     default: 'Petter',

    6.   },

    7.   userInfo: Object,

    8.   tags: Array,

    9. }) 

    使用 TS 类型声明:

     
      
    1. const props = defineProps<{ 

    2.     foo: string 

    3.     bar?: number

    4. }>()

    注:两个写法不可以一起进行使用,也就是一个 defineProps 不能既使用 TS 类型声明,也使用基础用法。

    1. withDefaults:这个方法并非属于编译器宏(compiler macros )api,但是这个 api 由defineProps衍生而出。在 TS 类型声明下无法进行设置默认值,这个 api 主要是为了解决这个场景。

     
      
    1. withDefaults(defineProps<{

    2.  size?: number

    3.  labels?: string[]

    4. }>(), {

    5.  size: 3,

    6.  labels: () => ['default label']

    7. })

    1. defineEmits:这个 api 也很好理解,就是定义 emits 相关信息。不过使用和以前有点不一样。

      基础使用:

     
      
    1. // 声明

    2. const emits = defineEmits(['change', 'delete'])

    3. // 使用

    4. emits('change')

    TS声明类型:

     
      
    1. // 声明

    2. const emit = defineEmits<{ (e: 'change', id: number): void (e: 'update', value: string): void }>()

    3. // 使用

    4. emits('change',1)

    1. defineExpose:在传统的 Vue 组件中,所有暴露在模板上的东西都隐含地暴露在组件实例上,也就是父组件可以通过ref 或者子链可以全量获取到子组件所有的属性、方法。大多数时候,这种全量暴露是过度的,而 vue3 setup 中必须进行手动暴露。

     
      
    1. const a = 1

    2. const b = ref(2)

    3. defineExpose({ a, b, })

    注意:目前发现defineExpose暴露出去的属性以及方法都是 unknown 类型,如果有修正类型的方法,欢迎评论区补充。

    hook api

    注:useContext API 被弃用,取而代之的是更加细分的 api。

    1. useAttrs:见名知意,这是用来获取 attrs 数据,但是这和 vue2 不同,里面包含了 class属性方法

      在 vue2 中封装组件透传属性、方法你可能这么写:

    <component v-bind='$attrs',v-on='$listeners'></component>
    

    vue3 里删除了 $listeners,新写法:

     
      
    1. <template>

    2.  <component v-bind='attrs'></component>

    3. </template>

    4. <srcipt setup lang='ts'>

    5.    const attrs = useAttrs();

    6. <script>

    1. useCSSModule:CSS Modules 是一种 CSS 的模块化和组合系统。vue-loader 集成 CSS Modules,可以作为模拟 scoped CSS。允许在单个文件组件的setup中访问CSS模块。此 api 本人用的比较少,不过多做介绍。

    2. useSlots: 顾名思义,获取插槽数据。

    3. useCssVars: 此 api 暂时资料比较少。介绍v-bind in styles时提到过。

    详情请见:github.com/vuejs/rfcs/…[6]

    1. useTransitionState: 此 api 暂时资料比较少。

    2. useSSRContext: 此 api 暂时资料比较少。

    setup 目前存在的限制

    修改选项配置需要单开一个 script

    配置项的缺失,有时候我们需要更改组件选项,在setup中我们目前是无法做到的。我们需要在上方再引入一个 script,在上方写入对应的 export即可。

     
      
    1. <script>

    2.    export default {

    3.        name: 'YourName',

    4.        inheritAttrs: false,

    5.        customOptions: {},

    6.    } 

    7. </script>

    8. <script setup>

    9.   // your code

    10. </script>

    注意:Vue 3 SFC 一般会自动从组件的文件名推断出组件的 name。在大多数情况下,不需要明确的 name 声明。唯一需要的情况是当你需要 <keep-alive> 包含或排除或直接检查组件的选项时,你需要这个名字。

    与 TS 与 ESLint 不是完美融合

    1. @typescript-eslint/no-unused-vars规则不兼容,此规则含义为定义了,未进行使用。该规则其实影响不大,关闭即可。

    2. 与导入的类型声明不兼容,当你通过解构的方式去导入类型,setup sugar 会进行自动导出。这时候,你就会收到 TS 的一条报错:此为类型,但被当作值使用。解决办法:类型导出使用export default导出或者引入时使用import * as xx来进行引入。

      感谢评论区补充:import type { test } from "./test";如此书写,也是可以解决的。

      关于这一点,也许你会想着在上方写一个 script 进行导入,但是这是不行的。在上方 script 导入的东西,也会被自动导出。详情见:github.com/vuejs/vue-n…[7]

    必须安装新的插件

    集成开发环境需要为这个新的 <script setup> 模型提供专门的处理,以便提供模板表达式类型检查 / 道具验证等。安装Volar也是为了这个目的。

    vue3 中如何实现国际化

    1. 下载最新的vue-i18n,当前版本"vue-i18n": "^9.1.7"

    2. src 下创建文件夹locales,创建好对应语言文案(这里最好使用 json)。

     
      
    1. import en from "./en.json";

    2. import zhHans from "./zh-cn.json";

    3. import zhHant from "./zh-hk.json";

    4. import { createI18n } from "vue-i18n";

    5. import { judgeLang } from "@/utils/url";

    6. const messages = {

    7.    en: en,

    8.    "zh-hans": zhHans,

    9.    "zh-hant": zhHant,

    10. };

    11. const i18n = createI18n({

    12.    locale: judgeLang(),

    13.    messages,

    14. });

    15. export default i18n;

    1. main.ts中引入i18n

     
      
    1. import { createApp } from "vue";

    2. import App from "./App.vue";

    3. import router from "./router";

    4. import store from "./store";

    5. import i18n from "@/locales/index";

    6. createApp(App).use(store).use(router).use(i18n).mount("#app");

    1. 创建一个i18n hook

     
      
    1. import { provide, inject } from "vue";

    2. import { useI18n } from "vue-i18n";

    3. export function useProvideI18n(): void {

    4.    const { t } = useI18n();

    5.    // 注入翻译函数

    6.    provide("t", t);

    7. }

    8. export function useInjectI18n(): (text: string) => string {

    9.   const t = inject("t") as (text: string) => string;

    10.   return t;

    11. }

    1. 在 app.vue,进行注入。随后,便可在各处进行接收使用。

    2. 下载 i18n Ally,可查看实时翻译(强烈推荐)。

    vue-i18n 详情请见:kazupon.github.io/vue-i18n/zh…[8] i18n Ally 插件详情请见:github.com/lokalise/i1…[9]

    vue3.2新增有意思的东西

    v-memo(Vue3.2 新增)

    记录指令下的模板树。该指令期望一个数组,如果数组内的值,都没有发生更新,那么指令下的模板树也不会发生更新。

     
      
    1. <div v-memo="[valueA, valueB]">

    2.   ...

    3. </div>

    当组件重新渲染时,如果valueAvalueB保持不变,<div>则将跳过此组件及其子组件的所有更新。实际上,即使是 Virtual DOM VNode 创建也将被跳过,因为可以重复使用子树的记忆副本。

    官网提到v-memo仅用于性能关键场景中的微优化,一般使用到的地方应该是渲染大型v-for列表(其中length > 1000)。

     
      
    1. <div v-for="item in list" :key="item.id" v-memo="[item.id === selected]">

    2.   <p>ID: {{ item.id }} - selected: {{ item.id === selected }}</p>

    3.   <p>...more child nodes</p>

    4. </div>

    v-bindin<style>(实验性语法)

    支持在单文件组件样式中使用组件状态驱动的CSS变量。其实,关于这个提案已经持续很久了(换了写法而已),本质上是利用CSS var() 函数

     
      
    1. <template>

    2.   <div class="text">hello</div>

    3. </template>

    4. <script>

    5.   export default {

    6.     data() {

    7.       return {

    8.         color: 'red',

    9.         font: {

    10.           size: '2em',

    11.         },

    12.       }

    13.     },

    14.   }

    15. </script>

    16. <style>

    17.   .text {

    18.     color: v-bind(color);

    19.     /* 表达式需用引号括起来 */

    20.     font-size: v-bind('font.size');

    21.   }

    22. </style>

    你可以在这里看见更多有关信息 github.com/vuejs/rfcs/…[10]

    你可能会遇到的问题

    移动端调试工具 vConsole 发生栈溢出

    一般移动端调试都是使用vConsole轻量好用,但是目前对 Vue3 兼容性不好,使用到一定时间,会出现栈溢出。这里推荐另外一个调试工具erudaeruda目前使用起来并没有大的问题,但是这个插件特别大,500 多 kb 是对于移动端是无法忍受的,即便压缩后也有 100 多 kb。这里我们只要根据环境判断,利用 script 动态插入就好了。

     
      
    1. export default function debugInit(): void {

    2.   const script = document.createElement("script");

    3.   script.type = "text/javascript";

    4.   script.src = "//cdn.bootcdn.net/ajax/libs/eruda/2.3.3/eruda.js";

    5.   document.getElementsByTagName("head")[0].appendChild(script);

    6.   script.onload = function () {

    7.     window.eruda.init();

    8.   };

    9. }

    慎用无根标签的组件

    目前 vue3 中我们已经不需要强制组件有一个根标签了,但是有些情况下,表现并不太好。

    例如:transition组件目前和此种写法偶发出现问题。

    你在Vue3的使用中,有遇到什么坑或者经验之谈吗?可以在评论区留下你宝贵的建议哦~

    参考资料

    [1]

    cli.vuejs.org/zh/guide/: https://link.juejin.cn?target=https%3A%2F%2Fcli.vuejs.org%2Fzh%2Fguide%2F

    [2]

    marketplace.visualstudio.com/items?itemN…: https://link.juejin.cn?target=https%3A%2F%2Fmarketplace.visualstudio.com%2Fitems%3FitemName%3Djohnsoncodehk.volar

    [3]

    github.com/vuejs/rfcs/…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Frfcs%2Fdiscussions%2F296

    [4]

    github.com/vuejs/rfcs/…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Frfcs%2Fpull%2F222

    [5]

    github.com/vuejs/rfcs/…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Frfcs%2Fpull%2F227

    [6]

    github.com/vuejs/rfcs/…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Frfcs%2Fblob%2Fmaster%2Factive-rfcs%2F0043-sfc-style-variables.md

    [7]

    github.com/vuejs/vue-n…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Fvue-next%2Fissues%2F3238

    [8]

    kazupon.github.io/vue-i18n/zh…: https://link.juejin.cn?target=https%3A%2F%2Fkazupon.github.io%2Fvue-i18n%2Fzh%2Fintroduction.html

    [9]

    github.com/lokalise/i1…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Flokalise%2Fi18n-ally%2Fblob%2Fmaster%2FREADME.md

    [10]

    github.com/vuejs/rfcs/…: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fvuejs%2Frfcs%2Fblob%2Fmaster%2Factive-rfcs%2F0043-sfc-style-variables.md

     


————————————————
版权声明:本文为CSDN博主「是云呀!」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yunbabac/article/details/120365666

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值