Vue3

作者: 李霖弢 | 来源:发表于2021-08-21 17:33 被阅读0次

主要特点

  • Vue3 通过 ES6 的 Proxy 代理整个对象,不再使用 defineProperty(getter/setter)监听对象单个属性,性能有所提升。
    因 IE 11 不支持 Proxy,且 Babel 也无法将 Proxy 转为 ES5,Vue3 无法兼容 IE11
  • Vue3 优化了diff 算法(不再比对所有dom)和 渲染算法(闭包缓存),性能更强大
  • Vue3 引入了组合式API:setup,将为同一功能服务的代码尽量写在一起,代码结构更清晰。

构建工具

  • Vue2 通过 vue-cli (webpack)构建
  • Vue3 通过 @vue/cli (基于webpack)构建,或直接通过 Vite 构建
Vite

目前支持 vue 和 react
仅支持 ES Module,不支持 CommonJS。

  • 本地开发运行时,不进行预打包和编译。通过浏览器本身支持的 ES Module 语法,仅请求并编译当前所需的模块,因此运行和热更新时都会更快。
  • 正式发布时和 webpack 区别不大。

与 Vue2 的一些语法区别

创建vm
  • 2中通过new Vue({render: h => h(App)}).$mount('#app')创建实例,3中通过Vue.createApp(App).mount('#app')创建
  • 2中.component.directive.use都是Vue的方法,3中是vm实例的方法
生命周期
  • 使用beforeUnmountunmounted代替beforeDestroydestroyed
组件
  • 2中一个template中必须有一个根元素,3中没有该限制,且支持通过$attrs取得引用元素的class属性
<my-component class="baz"></my-component>

<template>
  <p :class="$attrs.class">Hi!</p>
  <span>This is a child component</span>
</template>
  • v-model 的默认 prop 不再是 value,而是modelValue
    默认emit方法不再是input,而是update:modelValue
    通过v-model:xxx来将modelValue改为xxx而不再使用options的model属性修改,因此也可以实现同一组件上共存多个v-model
    新增通过modelModifiers自定义v-model修饰符
<HelloWorld v-model="aaa"/>
export default {
  components: {
    HelloWorld
  },
  data(){
    return {
      aaa:"i am aa in home"
    }
  },
  watch:{
    aaa(){
      console.log("watch aaa change")
    }
  }
}
...
export default {
  name: 'HelloWorld',
  props: {
    modelValue: String,
  },
  mounted(){
    this.$emit("update:modelValue","jjwjjw")
  }
};
  • options新增emits属性,用于传入该组件中所有需要 $emit 的事件数组或对象(用于校验)
    删除了事件的.native修饰。如包含了原生事件同名的事件,则会覆盖原生事件的监听
//此时对custom元素的点击事件不会触发xxx
<custom @click="xxx"/>
app.component('custom', {
  emits: ['click'],
  mounted() {
    this.$emit("click", "hello world");
  },
})
  emits: {
    // 没有验证
    click: null,
    // 验证submit 事件
    submit: ({ email, password }) => {
      if (email && password) {
        return true
      } else {
        console.warn('Invalid submit event payload!')
        return false
      }
    }
  },
  • 异步加载组件
    使用defineAsyncComponent代替原来的直接加载
指令
  • v-if 和 v-for 可以在一个元素上同时生效了,但 v-if 优先级更高,因此其中无法引用 v-for 里的变量
  • v-if 不再需要 key,v-for 的 key 可以配置在 template 中而非实际元素
api

Vue.prototype 替换为 config.globalProperties


组合式api setup

用于解决 mixins 的痛点,实现高内聚低耦合,将服务于每种功能的 data、computed、methods、watch 代码尽量书写在一起。其返回值会根据类型,落实到上述属性中。
setup 的调用发生在 props 之后,data property、computed property 、methods 解析之前,其中不存在指向当前组件实例的 this

参数

第一个参数通常命名为 props,即组件的 props,为一个 reactive 实例
第二个参数通常命名为 context,包含如下属性:

  • attrs 属性,非响应式对象,等同于 $attrs
  • slots 插槽,非响应式对象,等同于 $slots
  • emit 触发事件,方法,等同于 $emit
  • expose 暴露公共 property (函数)
响应性API
  • reactive
    传入一个对象进行 深层递归 Proxy处理,并解包该对象中存在的 ref 属性,且与其保持响应式连接。
    返回一种特殊的 Proxy 实例,对该实例的属性赋值 ref 实例时,也会自动解包
const count = ref(1)
const obj = reactive({ count })

// ref 会被解包
console.log(obj.count === count.value) // true

// 它会更新 `obj.count`
count.value++
console.log(count.value) // 2
console.log(obj.count) // 2

// 它也会更新 `count` ref
obj.count++
console.log(obj.count) // 3
console.log(count.value) // 3



const count2= ref(1)

obj.count2 = count2

console.log(obj.count2) // 1
console.log(obj.count2 === count2.value) // true
  • ref
    返回 RefImpl 实例,一个具有 value 属性的响应式对象
    如果传入值为基本数据类型,则直接赋值给 value。如果传入值为对象,则通过 reactive 深层响应式处理后,再赋值给 value。
  • isRef
    判断入参是否为 RefImpl 或 ObjectRefImpl 实例
  • unRef
    isRef(val) ? val.value : val 的语法糖
  • toRef
    将一个 reactive 实例的某个属性,以 ObjectRefImpl 实例返回出来。两者间保持响应式连接。
    如该属性不存在则新建属性。
    ObjectRefImpl 实例的变化本身不会触发视图更新
import { reactive, ref, isRef, unRef, toRef, toRefs } from "vue";

const counter = ref(0)
console.log(counter) // { value: 0 }
console.log(counter.value) // 0

const state = reactive({});
const fooRef = toRef(state, "age");
fooRef.value = 100;
console.log(state.age); // 100
state.age++;
console.log(fooRef.value); // 101
  • toRefs
    将一个 reactive 实例返回为普通对象,该对象每个属性经过 toRef 处理,与原 Proxy 对象一一保持响应式连接
const state = reactive({
  foo: 1,
  bar: 2
})

const stateAsRefs = toRefs(state)

state.foo++
console.log(stateAsRefs.foo.value) // 2

stateAsRefs.foo.value++
console.log(state.foo) // 3
生命周期

组合式 API 上的生命周期钩子与选项式 API 的名称相同,但需要添加前缀 on

import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted } from 'vue'

// 在我们的组件中
setup (props) {
  const repositories = ref([])
  const getUserRepositories = async () => {
    repositories.value = await fetchUserRepositories(props.user)
  }

  onMounted(getUserRepositories) // 在 `mounted` 时调用 `getUserRepositories`

  return {
    repositories,
    getUserRepositories
  }
}

相关文章

网友评论

      本文标题:Vue3

      本文链接:https://www.haomeiwen.com/subject/cbwmbltx.html