vue3 新特性--学习笔记

974 阅读5分钟

Vue 团队于 2020 年 9 月 18 日晚 11 点半发布了 Vue 3.0 版本

本次主版本更新包含性能的改进,更小的 bundle 体积,对 TypeScript 更好的支持,用于处理大规模用例的全新 API

1. vue3.0相比2.0产生的变化,新特性

  • performance-性能
  1. 使update性能得到很大提高,提高1.3~2倍(为了提高性能,作者相当于将vue重写了一遍,推翻上一个版本并且兼容上个版本)
  2. SSR速度提高了2~3倍
  3. 最主要的是重写了虚拟Dom的实现,主要思路是跳过了静态节点,只处理动态节点
  • Tree shaking-精简无用代码

将按需打包融入到vue3.0中,用到什么打包什么,将没用的模块剪掉,最终打包出来的项目体积比较小

  • Fragment-碎片

vue2中创建template根节点时,只允许创建1个,用div包裹起来,无形中让整个页面的html层级加深。 vue3可以直接在template标签里写多个节点。

  • TypeScript

vue3.0之后底层都是基于TS写的,使用TS的好处是在大型项目开发,TS能有效的管控代码的编程感。不过在vue3中不使用TS也没问题。

  • Composition API (对于应用来说,是最需要了解的)

组合式API,替换原有的Options API

  • 根据逻辑相关性组织代码,提高可读性和可维护性
  • 更好的重用逻辑代码(避免mixins混入时命名冲突的问题)

依然可以延用 Options [ˈɒpʃnz] API

2.0:

(1)data返回一个函数,包含了响应式数据,实现状态私有化
(2)后续写方法,根据方法的情况,把它写在methods里。写在computed,watch里进行计算属性或监听,
还有筛选放在filters里
(3)会发现项目代码少还好,看着很清晰。如果项目代码很多,会发现这么写不利于代码的可读性以及可维护性

3.0
因此在3.0版本提出了组合式API的概念
(1)在composition API中提供了setup,它是composition API的入口。
(2)将我们要实现的功能,它具体要实现的状态,方法,以及周期函数全部封装到模块下,将封装好的模块
全部导入到setup中,从setup中统一暴露出去,供模版来使用

mixins: 是有缺陷的,简单使用还可以,如果项目比较大,自己要往全局混入,别人也要全局混入,很有可能产生冲突,就比较难搞。

  • Proxy

vue2.0 响应式数据基于Object defineProperty,它处理也可以,但存在局限性和不太好的地方。

ES6 为我们提供了Proxy,它在数据劫持方面做的要比Object defineProperty强很多

vue3.0响应式原理不再基于 Object.defineProperty

developer.mozilla.org/zh-CN/docs/…

2. 基于 vue/cli 配置 vue3.0

  • 在@vue/cli基础上,通过vue-cli-plugin-vue-next插件,让脚手架支持vue3.0的应用
$ npm install -g @vue/cli
$ vue --version
$ vue create xxx
$ vue add vue-next

要求cli的版本要高于4.3.1

3. 基于vite配置vue3.0

由 vue 作者尤雨溪开发的 web 开发工具,直接基于这个工具构建的项目就是vue3.0的项目

github.com/vitejs/vite

(非常快,不像webpack需要将所有东西打包编译,编译完再渲染)

  • 基于浏览器原生 ES imports 的开发服务器(利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用)
  • 同时不仅有 Vue 文件支持,还搞定了热更新,而且热更新的速度不会随着模块增多而变慢
$ npm init vite-app xxx  // 创建项目
$ cd xxx
$ npm install
$ npm run dev
$ npm run build

4. 掌握setup和响应式系统API

vue-composition-api-rfc.netlify.app/zh/api.html

4.1 setup:

setup 函数是一个新的组件选项,作为在组件内使用 Composition API 的入口点

  • 初始化属性(props)和beforeCreate之间调用
  • 可以接收 props 和 context
  • this在setup()中不可用
export default {
  props: {
    title: String,
  },
  setup(props) {
    // props是基于proxy代理的响应式数据
    // 监听props改变,props改变会触发回调函数重新执行
    watchEffect(() => {
      console.log(`title is: ` + props.title);
    }); 

  }
};

props是响应式的,可以基于watchEffect/watch监听,解构赋值后则无效(不再是响应式数据)

components API 放弃data,methods这些方法,所有的一切都通过vue提供的components API ,放在setup中去处理

export default {
  props: { title: String },
  setup() {
    let supNum = 0,
      oppNum = 0;
    let change = lx => {
      lx === 0 ? supNum++ : oppNum++;
    };
  // return的内容可以直接在模板中渲染使用,但此时数据并不是响应式数据,因此数据也不更新
    return {
      supNum, oppNum, change
    };}};
    

4.2 构建响应式数据

方法一:ref(一般处理简单值的响应式)

原理:define property监听value值,value改变通知组件重新渲染

接受一个参数值并返回一个响应式且可改变的 ref 对象

  • ref 对象拥有一个指向内部值的单一属性 .value
  • 当ref在模板中使用的时候,它会自动解套,无需在模板内额外书写 .value
 import { ref } from "vue";
export default {
  setup() {
    let supNum = ref(0),
      oppNum = ref(0);
    let change = lx => {
      lx === 0 ? supNum.value++ : oppNum.value++;
    };
    return {
      supNum,oppNum,change
    };
  }
};

以上方法存在问题:想用一个响应式数据就得用ref一次,很麻烦。可以整体变成一个对象

export default {
  setup() {
    let state = ref({
        supNum:0,
        oppNum:0
    })
    let change = lx => {
      lx === 0 ? state.value.supNum++ : state.value.oppNum++;
    };
    return {
      state,change
    };
  }
};

此时change方法也发生了改变,写起来依然很麻烦。

方法二:reactive

基于proxy对数据进行深度监听,以此构建响应式

接收一个普通对象,然后返回该普通对象的响应式代理

等同于2.x的Vue.observable()

  • 响应式转换是“深层的”的,会影响对象内部所有嵌套的属性
export default {
  setup() {
    let state = reactive({
        supNum:0,
        oppNum:0
    })
    let change = lx => {
      lx === 0 ? state.supNum++ : state.oppNum++;
    };
    return {
      state,change
    };
  }
};

state()对象的形式在组件内使用需要{{state.supNum}}这么引用,可以通过toRefs方式将reactive中每一项变为ref响应式数据,就可以在组件中直接使用。

此时return返回:...toRefs(state)

4.3 响应式工具集

  • isRef:检测是否是ref对象,是返回true,不是返回false
  • toRefs:转变为ref响应式数据
  • unref:如果参数是一个ref就返回它的value值,不是就返回参数本身。是val=isRef(val)?val.value:val的语法糖。