chenfei-hnu / Blog

个人整理的跟前端相关的文档 ( This is some front-end development related documentation )
9 stars 2 forks source link

Vue3.0新特性 #26

Open chenfei-hnu opened 4 years ago

chenfei-hnu commented 4 years ago

源码地址:https://github.com/vuejs/vue-next

函数式 api

参考文章: https://segmentfault.com/a/1190000020791649 https://segmentfault.com/a/1190000019625934 https://segmentfault.com/a/1190000017088044

1.setup

<template>
  <button @click="increment">
    Count is: {{ state.count }}, double is: {{ state.double }}
  </button>
</template>

<script>
import { reactive, computed } from 'vue'

export default { 
    props: {
        name: String
    },
    setup(props, context) {
        console.log(props.name);
        const state = reactive({
            count: 0,
            double: computed(() => state.count \* 2)
        })

        function increment() {
            state.count++
        }

        return {
            state,
            increment
        }
    }
}
</script>

setup函数是Vue Function API 构建的函数式写法的主逻辑,当组件被创建时,就会被调用,函数接受两个参数,分别是父级组件传入的props和当前组件的上下文context,声明所有响应属性、计算属性、观察者和生命周期 hooks,然后返回它们,以便在模板中使用

value, computed, watch, onMounted等方法都需要从外部import,在vue2中,watch、computed、data、method等API都是直接作为对象的属性,最大缺点是它本身并非有效的 JavaScript 代码,你需要准确了解模板中可以访问哪些属性,以及this关键字的行为,Vue 编译器需要将属性转换为可用的代码,因此我们无法享受自动提示或类型检查功能的帮助,代码规模变大,影响vue组件代码的可读性import引入的方式,需要写的代码量更少,可以封装更多的子函数、引用更多的公共函数去维护们的代码,代码的可读性变高

setup 调用介于 beforeCreate 和 created 之间,无法在这里使用 this 指向当前组件实例,如果需要访问一些内置属性,通过 context.attrs 访问其属性时,本质上代理对象会将访问指向组件的内部实例

使用 reactive声明state ,可以包装任何原语或对象,并返回其响应性引用,对于 computed state 的声明,使用 computed,两者本质上均是 Proxy 对象,直接通过声明普通函数的方式进行声明组件方法,对于 state 的变更,直接通过闭包使用 state 即可

setup 的返回值被称作 render context,就是模板中可以访问到的各种数据和方法的上下文对象当我们没有声明 template 属性时,还可以以h(...)的形式返回模板渲染函数

声明 state的几种形式

基础类型可以通过 ref 这个 api 来声明,const count = ref(0); 将js基础数据类型封装成对象,使得组件状态以引用的方式保存下来,从而可以被在setup中调用的不同的模块的函数以参数的形式传递

引用类型除了可以使用 ref 来声明,也可以直接使用 reactive

const state = reactive({
    count: 0
});

可以使用toRefs 对reactive返回的对象进行处理,使得其每个熟悉都通过ref进行处理

2.生命周期

每一个 vue2 中的组件生命周期函数,当前都对应一个生命周期 hook 之前created中初始化逻辑的代码,直接写在 setup 方法中即可

import { onMounted, onUpdated, onUnmounted } from "vue";

setup() {
  onMounted(() => { ... });
  onUpdated(() => { ... });
  onUnmounted(() => { ... });
}

3.代码复用

复用代码的逻辑本质上是利用这些 hook 来拆分业务逻辑与状态,将一些耦合在一起的代码抽离出来,同时以 use 前缀命名, 声明一个自定义的 hook,显式使用useXXX函数,而不用污染 Vue 原型

export default {
  setup() {
    const data = useSearch()
    return { data }
  }
}
function useSearch() { 
    ...fetch data
}

除了以 inline 的方式来声明,还可以将这些自定义的 hook 声明在单独的文件中,直接通过 import 导入即可,import useSearch from '@hooks/search'

源码方面改动

1.Typescript

学习资源链接https://github.com/vue3/vue3-News/issues/3

按需输出 JavaScript 版本
代码标准化利于团队开发
主流框架及最新特性的支持
便于重构和主流IDE支持
更多友好特性和检测

2.Vue3.0使用Proxy替代defineProperty实现数据监听

来源:https://juejin.im/post/5da29a87518825094e37301c

Object.defineProperty只能劫持对象的属性,需要遍历对象的每个属性,而Proxy是直接代理对象
Object.defineProperty对新增属性需要手动进行Observe,proxy可以直接拦截到对象的新增属性
Object.defineProperty 劫持的是对象的属性,新增属性时,需要重新遍历对象,再对新增的属性进行劫持
Proxy 对数组的监听更加方便,不必像Object.defineProperty需要进行很多hack处理
Proxy 作为新标准,浏览器厂商势必会对其进行持续优化,但它的兼容性也是块硬伤