Vue3.2五大新特性

600 阅读2分钟

/这是跟着B站的学习笔记,也加入了学习过程中自己的理解。感谢up主的讲解 /

五大新特性:

  1. 新的单文件组件特性:
  2. Web Components
  3. 性能提升
  4. 服务端渲染
  5. Effect 作用域API
  • setup语法糖 + TS + Volar === 真香

前置知识

  • 因为学习VUE3.2需要有vue3.0的前置知识,所以在学习过程中,我会把涉及到的前缀知识补充在这里
  1. Options API 和 Composition API 的区别

    • 二者的比较
    • Options API就是VUE2中那种把组件分成data、methods、props、各种生命周期这种一板一眼的方式,每个部分该写什么是很明确的,这样易于用户上手;但是一个组件过大以后,就会很麻烦,比如data里有很多数据,一个methods中可能包含20多个方法,你往往分不清哪个方法对应着哪个功能,难以区分每个数据要用在哪里,而且要去找对应的methods也很麻烦。
    • Composition API 就是根据逻辑相关性组织代码的,所以所以在代码组织上就要多花点心思了。但能提高可读性和可维护性;而且其有更好的类型推断,对ts更友好。
    • 使用场景:Vue3首推Composition API; 如果是中低复杂度的项目,可以用options API,如果是大型、高扩展、长期维护的项目就用Composition API。
  2. 运行时声明和类型声明

    • 运行时声明:即运行后才能声明,一开始无法确定。如vue2中子组件使用props接收值,但是只有运行后才能知道接收到了啥
    • 类型声明:ts的类型约束发生在编译的时候,这时还没有运行,所以可以先一步判断
    • 比较:ts类型声明拥有更完美的类型检验。我要学ts
  3. Compiler Macros(编译时宏命令)

    • 宏(Macro),是一种批量批处理的称谓。一般说来,宏是一种规则或模式,或称语法替换 。解释器或编译器在遇到宏时会自动进行这一模式替换。
  4. css module是啥?以前怎么没听过呀

  5. css中的var函数

项目搭建

  • 使用vite搭建项目 npm init vite@latest . -- --template vue-ts (呜呜,太感人了,一个命令就把项目搭建起来了)
  • npm run dev 运行项目(秒开,太顺滑了,呜呜,感谢祖师爷赏饭吃!)

setup 语法糖

基本用法:将setup写在script代码块上 <script setup lang="ts"></script>

  • 优点:
    1. 写法更简洁
    2. 顶层绑定将自动暴露给模板,不需要return了
    3. 原理:将模板内容转化为虚拟node节点,放在了setup函数中,这样即使setup函数没有return数据出去,但是我把你拿进来是一样的呀!山不向我走来,我就向山走去
  • 原本是:需要手动写setup()函数的
     <script lang="ts">
    import { defineComponent, ref } from "vue"
    export default defineComponent({
      setup() {
        const count = ref(1);
        const add = () => {
          count.value += 1
        }
        // 这里用return,模板中才能进行使用
        return {
          count,
          add
        }
      }
    })
    
  • 现在:加一个标签就好了,里面的代码会被自动编译成setup()函数的内容
      <script setup lang="ts">
          import {ref} from 'vue'
          const count = ref(1);
          const add = () => {
             count.value += 1
          }
      </script>   
    

setup 语法糖下组件的使用

  • 自动组件名推断:vue3中无法显式设置组件名,在命名缺省的情况下,vue3会自动根据文件名命名组件
  • 普通组件的使用:在vue2中引入组件还需要注册后才能使用,vue3中引入即可使用
  • 动态组件:还是用
  • 递归组件:递归即自己使用自己,因为vue3会自动命名组件,所以如果遇到import引入的同名组件优先级更高,所以引入的同名组件要取别名哦: import {Foo as newFoo} from './components'
  • 命名空间组件: 即将多个组件写入同一个导出组件,然后在目标页面一次性引入该导出组件即可,使用的时候就像对象那样

setup 语法糖下props的使用

  • props的使用————defineProps(这就是一个宏命令)

    1. 使用运行时声明: 从编译后的结果可以看到,还是放到了传统的props中去
     <script setup lang="ts">
      defineProps({
        title: {
          type:String,
          required:true,
          defaults:'默认值'
        },
        list: {
          // 注意这个type是vue提供的,不能像ts那样约束数组里的内容
          type: Array,
          required: true
        }
      })
    </script>
    
    1. 类型声明: 从编译后的结果可以看到,还是放到了传统的props中去
     <script setup lang="ts">
        const props = defineProps<{
        title?:type:string
        list:{id:number, content:string}[]
        }>()
        // 可以通过变量接收defineProps的返回值,并在script中使用
        console.log(props);
     </script>
    
    1. 注意,两种声明不能混用
  • props的默认值————widthDefaults

    1. 运行时声明可以添加默认值
    2. 类型声明的ts需要widthDefaults,所以写法变成了下面这样
      <script setup lang="ts">
       const props = widthDefaults(defineProps<{
       title?:type:string
       list:{id:number, content:string}[]
       }>(), {
          title:'ts的默认值'
       })
       // 可以通过变量接收defineProps的返回值,并在script中使用
       console.log(props);
    </script> 
    

setup 语法糖下自定义事件————defineEmits的使用

  • 作用——在vue2中我一直把它理解为是子组件向父组件传值的一种方法
  • 两种用法:普通写法在子组件中没有对数据类型进行约束;类型声明式则更好一点。
  • 普通写法:
       const emits = defineEmits(['parentClick','parentChange'])
       const handleClick = () => {
       // 子组件中对参数没有约束
         emits("parentClick",2)
       }
       const handleChange = () => {
         emits("parentChange")
       }
    
  • 类型声明式:既提供了类型的约束,也提供了类型的提示
        const emits = defineEmits<{
        // 这里对数据类型进行了约束!
        (e:'parentClick', data: number): void,
        (e:'parentChange'): void
        }>()
    
        const handleClick = () => {
          emits("parentClick",2)
        }
        const handleChange = () => {
          emits("parentChange")
        }
    

显示地暴露 ———— defineExpose

useSlots-useAttrs-await(插槽)

style v-bind

  1. css module 原来我在vue2中是这样写样式的:
   <script setup lang="ts">
   </script>

   <template>
   // 通过类名选择器来使用
     <p class="red">使用css module功能</p>
   </template>

   <style>
     .red{
     color:red
     }
   </style>

使用css module: 可以理解为css module维护了一个对象$style,类名是它的元素,所以template中可以访问到类名

   <script setup lang="ts">

   </script>

   <template>
     <p :class="$style.red">使用css module功能</p>
   </template>

   <style module>
     .red{
     color:red
     }
   </style>
  • module模块可以具名
    • 具名的好处,一是可以区分;二是可以在script中通过useCssModule来获取它。进而通过js,操作样式(我想多了,没办法修改它)
<script setup lang="ts">
  import { useCssModule } from 'vue';
  const box = useCssModule('box');
  function changeStyle() {
    console.log(box);
    
  }
</script>

<template>
  <p :class=[$style.red,box.outLook]>使用css module功能</p>
  <button @click="changeStyle">点击修改样式:暂时没法修改的</button>
</template>

<style module>
  .red{
  color:red
  }
</style>

<style module="box">
  .outLook{
    border:1px solid red;
    width: 200px;
    height: 20px;
    background-color: pink;
  }
</style>
  1. 状态驱动的动态css
  • vue2中是怎么样动态修改样式的?通过修改变量 + 三目运算符 + 切换不同的样式
  • 可以看到style中冗余了多余的样式,再者template中进行计算和判断的内容,没有很好的解耦
   <script setup lang="ts">
      import {ref} from 'vue'
      const flag = ref(false);
   </script>

   <template>
      <button :class="flag?'active':'no'" @click="flag = !flag">
          点击修改样式
       </button>
   </template>

   <style>
     .active {
       color: red;
     }
     .no {
       color:blue;
     }
   </style>
  • vue3中: 形式简洁、也解耦了
   <script setup lang="ts">
      import {ref} from 'vue'
      const fontColor = ref('blue');
   </script>

   <template>
      <button class="active" @click="fontColor = 'red'">点击修改样式</button>
   </template>

   <style>
     .active {
       color: v-bind(fontColor);
     }
   </style>

Web components

  • web components入门
  • 背景:写一个组件,可以跨框架使用,即vue、react都能使用。既然是独立于框架的,为啥这里又可以用vue来写呢?因为vue提供了一个API供快速写 Web components,写完以后,将其导出,还是通用的一个组件。
  • 基本使用:写一个ts文件,在该文件中写通用组件,所写的ts文件最终要在main.ts中导入,供全局使用。可见这种写法还是很繁琐的,跟原生的web components没区别
        import { defineCustomElement } from "vue";
        // 步骤1:使用defineCustomElement写一个html页面
        const MyCustomElement = defineCustomElement({
          props: {},
          template: "<div class='color'>MyCustomElement</div>",
          styles: ['.color{color:red}']
        });
    
        // 步骤二:使用customElements.define将页面变成组件my-custom-element
        customElements.define("my-custom-element", MyCustomElement);
    
  • 使用sfc来创建 Web components
    • 优点:可以用写vue组件的形式写上面defineCustomElement里的那一大串内容,注意这个组件的后缀名要是'.ce.vue'
       // Loading
    
  • 注意在vite.config.ts中进行配置,获取带有运行时解析的vue文件
        resolve: {
        alias: [
          {
            find: "vue",
            replacement: "vue/dist/vue.esm-bundler.js",
          },
        ]
        }
    

性能提升

  • v-memo指令

服务端渲染

  • @vue/server-renderer

Effect 作用域API

  • effectScope用于直接控制响应式API(computed和watch)的执行时机

volar插件

  • 很好地支持了vue3的新特性、支持ts
  1. 语法糖提示,如ref sugardengdeng,这个要在volar插件中进行设置

  2. 把编辑器分成三分