vue3 相关新特性

285 阅读3分钟

1、vue3 新特性

vue3 新特性:性能更高、体积更小、更利于复用、代码维护更方便

  • 数据响应式原理重新实现(ES6proxy替代 ES5Object.definedPropety),大大优化了响应式监听的性能

  • 原来检测对象属性的变化,需要一个个对属性递归监听,proxy 可以直接对整个对象劫持

  • vue3源码用TypeScript(ts)重写了,更好的类型推导,类型检测更为严格、更稳定

  • 模块可以有多个根元素(template里面可以有多个根元素)

  • optionsAPI(旧)compositionAPI(新),可以更好的逻辑复用 与代码组织

  • 虚拟 DOM -新算法更快、更小

2、基于 vite 创建 vue3 的工程化项目

法1 yarn

yarn  create  vite-app  vue3-study(项目名称)
cd  vue3-study
yarn 
yarn  dev

法2 npm

npm  init  vite-app  vue3-study(项目名称)
cd   vue3-study
npm  install 
npm  run  dev

image.png

可以看出,在 vue3 的工程化的项目中,vue 要做的事情很单纯:通过 main.js 把 App.vue 渲染到 index.html 的指定区域中。 其中:

  • App.vue 用来编写待渲染的模板结构
  • index.html 中需要预留一个 el 区域
  • main.jsApp.vue 渲染到了 index.html 所预留的区域中

插件:Vue VSCode SnippetsVue Language Features(Volar)

3、vue3 生命周期钩子函数

  • vue3 生命周期钩子函数
    • setup 创建实例前
    • onBeforeMount 挂载 DOM 前
    • onMounted 挂载 DOM 后
    • onBeforeUpdate 更新组件前
    • onUpdated 更新组件后
    • onBeforeUnMount 卸载销毁前
    • onUnmounted卸载销毁后

4、setup 函数

composition 的使用, 需要配置一个 setup 函数

  • setup 函数是一个新的组件选项, 作为组件中 compositionAPI 的起点
  • 从生命周期角度来看, setup 会在 beforeCreate 钩子函数之前执行
  • setup 中不能使用 this, this 指向 undefined
  • 在模版中需要使用的数据和函数,需要在 setup 返回
<template>
  <div>
    <p>打个招呼:{{ hello }}</p>
  </div>
</template>

<script>
export default {
  setup() {
    const hello = "你好呀";
    return { hello };
  },
};
</script>

5、reactive 函数

reactive 函数

  • setup 需要返回值, 返回的值才能在模板中使用
  • 默认的普通的值不是响应式的, 需要用 reactive 函数
  • reactive 函数将复杂数据类型转换成响应式数据(返回该对象的响应式代理)
<template>
  <div>
    <!-- 一点击,视图层的 name 变成“李四” -->
    <p>我是{{ obj.name }}</p>
    <button @click="fn">按钮</button>
  </div>
</template>

<script>
import { reactive } from "vue";
export default {
  setup() {
    const obj = reactive({
      name: "前端小白兔",
      age: 18,
      hobby: "敲代码",
    });
    const fn = () => {
      obj.name = "李四";
      console.log(obj); //Proxy {name: '李四', age: 18, hobby: '敲代码'}
      console.log(obj.name); //李四
    };
    return { obj, fn };
  },
};
</script>

6、ref 函数

reactive 处理的数据, 必须是复杂类型, 如果是简单类型无法处理成响应式, 由此 ref 函数诞生!

作用: 对传入的数据(一般简单数据类型),包裹一层对象, 转换成响应式

  • ref 函数接收一个的值, 返回一个 ref 响应式对象, 有唯一的属性 value
  • setup 函数中, 通过 ref 对象的 value 属性, 可以访问到值
  • 在模板中, ref 属性会自动解套, 不需要额外的 .value
  • ref 函数也支持传入复杂类型,传入复杂类型,也会做响应式处理(例如Array)
  • 明确的对象,明确的属性,用 reactive ,其他用 ref
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="addFn">按钮</button>
    <h1 v-if="flag">{{ flag }}</h1>
  </div>
</template>

<script>
import { ref } from "vue";
export default {
  setup() {
    const count = ref(1);
    const flag = ref(true);
    const addFn = () => {
      count.value++;
      flag.value = !flag.value;
    };
    return { count, flag, addFn };
  },
};
</script>

7、toRef 函数

  • toRef(目标对象,指定变成响应式对象的属性)
<template>
  <div>
    <!-- 一点击全部变成了新数据 -->
    <p>我是{{ obj.name }},我今年{{ obj.age }},我的爱好是{{ obj.hobby }}</p>
    <p>我是{{ name }},我今年{{ age }},我的爱好是{{ hobby }}</p>
    <button @click="fn">按钮</button>
  </div>
</template>

<script>
import { reactive, toRef } from "vue";
export default {
  setup() {
    const obj = reactive({
      name: "前端小白兔",
      age: 18,
      hobby: "敲代码",
    });
    const name = toRef(obj, "name");
    const age = toRef(obj, "age");
    const hobby = toRef(obj, "hobby");
    const fn = () => {
      name.value = "张三";
      age.value = 30;
      hobby.value = "玩魔方";
    };
    return { obj, fn, name, age, hobby };
  },
};
</script>

8、toRefs 函数

使用场景: 如果对一个响应数据, 进行解构 或者 展开, 会丢失他的响应式特性!

原因: vue3 底层是对 对象 进行监听劫持

作用: 对一个响应式对象的所有内部属性, 都做响应式处理

  • reactive 的响应式功能是赋值给对象的, 如果给对象解构或者展开, 会让数据丢失响应式的能力
  • 使用 toRefs 可以保证该对象展开的每个属性都是响应式的

<template>
  <div>
    <p>我是{{ name }},我今年{{ age }},我的爱好是{{ hobby }}</p>
  </div>
</template>

<script>
import { reactive, toRefs } from "vue";
export default {
  setup() {
    const obj = reactive({
      name: "前端小白兔",
      age: 18,
      hobby: "敲代码",
    });

    return { ...toRefs(obj) };
  },
};
</script>
<template>
  <div>
    <p>我是{{ name }},今年{{ age }}岁了,我的爱好是{{ hobby }}</p>
    <button @click="fn">按钮</button>
  </div>
</template>

<script>
import { reactive, toRefs } from "vue";
export default {
  setup() {
    const obj = reactive({
      name: "前端小白兔",
      age: 18,
      hobby: "敲代码",
    });
    const newobj = toRefs(obj);
    const fn = () => {
      newobj.name.value = "李四";
      newobj.age.value = 24;
      newobj.hobby.value = "魔方";
    };
    return { ...newobj, fn };
  },
};
</script>
<template>
  <div>
    <p>我是{{ name }},今年{{ age }}岁了,我的爱好是{{ hobby }}</p>
    <button @click="fn">按钮</button>
  </div>
</template>

<script>
import { reactive, toRefs } from "vue";
export default {
  setup() {
    const obj = reactive({
      name: "前端小白兔",
      age: 18,
      hobby: "敲代码",
    });
    const fn = () => {
      obj.name = "李四";
      obj.age = 24;
      obj.hobby = "魔方";
    };
    return { ...toRefs(obj), fn };
  },
};
</script>

9、模板中 ref 的使用(获取 DOM)

<template>
  <div>
    <div class="box1" ref="dom1">我是 box1</div>
    <div class="box2" ref="dom2">我是 box2</div>
  </div>
</template>

<script>
import { onMounted, ref } from "vue";
export default {
  setup() {
    const dom1 = ref(null);
    const dom2 = ref(null);
    onMounted(() => {
      console.log(dom1, "111"); //RefImpl {}
      console.log(dom2, "222"); //RefImpl {}
      console.log(dom1.value, "111"); // <div class="box1">我是 box1</div> '111'
      console.log(dom2.value, "222"); // <div class="box2">我是 box2</div> '222'
    });
    return { dom1, dom2 };
  },
};
</script>