【前端进阶】Vue 3 新特性详解

文章目录

    • 1 为什么学vue3 ?
    • 2 vite 基本使用
    • 3 创建vue 项目
    • 4 选项API和组合API
    • 5 组合API-setup 函数
    • 6 组合API-生命周期
    • 7 组合API reactive 函数
    • 8 组合API toRef函数
    • 9 组合API toRefs 函数
    • 10 组合API ref函数
    • 11 组合API computed函数
    • 12 组合API watch函数
    • 13 组合API ref属性
    • 14 组合API 父子通讯
    • 15 组合API 依赖注入
    • 16 v-model 语法糖
    • 17-mixins 语法

1 为什么学vue3 ?

目标 了解vue3 现状,以及他的优点,展望他的未来

vue3现状:

  • vue-next 2020年09月18日,正式发布vue3.0 版本,但是由于刚发布周边生态不支持,大多数开发者人处于观望
  • 现在主流组件库都已经发布了支持vue3.0的版本,其他生态也在不断的完善中,这是趋势
    • element-plus: 基于vue3.0 的桌面端组件库
    • vant: vant3.0 版本 有赞前端团队 开源移动端组件库
    • ant-design-vue: Ant Design Vue2.0 版本,社区根据蚂蚁 antdesign 开发

vue3优点:

  • 最火框架,他是国内最火的前端框架之一,官方文档为中文文档
  • 性能提升,运行速度是vue2.x 的 1.5倍
  • 体积更小,按需编译 体积比vue2.x 要更小
  • 类型推断,更好的支持ts 这也是一个趋势
  • 高级给予,暴露了更底层的API和提供更先进的内置组件
  • 组合API,能够更好的组织逻辑,封装逻辑,复用逻辑

vue3展望:

  • 这是趋势,越来越多的企业将来肯定会升级到vue3.0
  • 大型项目,由于对ts的友好 越来越多大型项目可以用vue3.0

总结 为什么要学习vue3?

  • 使用市场学习流行的技术 提高自己的竞争力,给自己加薪

2 vite 基本使用

目标:了解vite是什么,使用vite创建vue项目,用来学习vue3

vite是什么?

  • 他是一个更加轻量(热更新速度块,打包构建速度快)的vue项目脚手架工具

  • 它相对于vue-cli它默认安装的插件非常少 随着开发过程以来增多,需要自己额外配置

  • 所以:在单纯学习vue3语法会使用它,后面做项目可以继续使
    用vue-cli

vite 基本使用:

  • 创建项目 npm init vite-app 项目名称 或者 yarn create vite-app 项目名称
  • 安装依赖 npm i 或者 yarn
  • 启动项目 npm run dev 或者 yarn dev

总结:vite 是什么?

  • 下一代前端开发与构建工具

  • 使用vite创建项目 学习vue3 语法 使用vue-cli 创建项目正式开发

3 创建vue 项目

目标:掌握如何创建vue3 应用实例

基本步骤:

  • 在main.js 导入createApp 函数
  • 定义App.vue 组件 导入main.js
  • 使用createApp函数基于App.vue组件创建应用实例
  • 挂在之index.html 的app容器
import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);
app.mount("#app");

总结:如何创建vue应用实例?

通过createApp创建应用实例 -> 拓展功能将来都是在app上进行

4 选项API和组合API

目标:理解什么是选项API写法 什么是组合API写法

vue2.x 中的选项API 是在各个选项中实现一个共同逻辑,代码是分散的,项目过大时,不好维护,无论是阅读性还是可维护性都比较差

vue3.x 中组合式API 的每个逻辑是集中在一起的,便于后期的维护,书写起来,也不用对照前后的代码,去书写一个功能,阅读性,可维护性更高

什么是选项API写法:Option API

  • 咱们再vue2.x 项目中使用的就是选项API 写法

    • 代码风格:data选项书写数据 methods 选项写方法 一个功能逻辑的代码比较分散
  • 优点:易于学习和使用 写代码的位置已经约定好

  • 缺点:代码组织性比较差,相似的逻辑代码不便于复用,逻辑复杂代码多了就不好阅读

  • 补充:虽然提供mixins用来封装逻辑,但是出现数据函数覆盖的概率比较大,不好维护,容易出现bug,变量的隐式声明。

什么是组合API写法:Componsition API

  • vue3.x 项目中 将会使用组合API 写法

    • 代码风格:一个功能逻辑的代码组织在一起(包含数据,函数)
  • 优点:功能逻辑复杂繁多的情况下,各个功能逻辑代码组织在一起,便于阅读和维护

  • 缺点:需要有良好的代码组织能力和拆分逻辑的能力

  • 补充:为了能让大家更好的过度到vue 3.0 ,也会支持选项API

5 组合API-setup 函数

目标:掌握setup函数的基本使用

使用细节:

  • setup 是一个新的组件选项 作为组件中使用组合API的起点
  • 从组件的生命周期来看 他的执行再组件实例创建之前 vue2.x beforeCreate 执行
  • 这就意味着在setup 函数中 this 还不是组件实例 this此时是undefined
  • 在模板中需要使用的数据和函数 需要在setup返回出去

6 组合API-生命周期

vue2 生命周期钩子 vue3生命周期钩子
beforeCreate setup
创建实例 created
beforeMount onBeforeMount
挂载DOM mounted onMounted
beforeUpdate onBeforeUpdate
组件更新 updated onUpdated
beforeDestroy onbeforeUnmount
组件销毁 destroyed onUnmounted

在vue2.x 中 钩子函数选项只可以写一个

在vue3.0 中 钩子函数可以定义多个 用于实现不同的逻辑

7 组合API reactive 函数

目标:掌握使用reactive函数定义响应式数据

定义响应式数据:

reactive 是什么?
他是一个函数
有什么用?
它可以定义一个复杂数据类型 成为响应式数据
怎么用?
const obj = reactive({
      name: "小王",
      age: 18,
    });
为什么要用?
因为vue3.0 生命的普通变量并不是响应式的
使用场景?
当需要定义一些复杂的响应式数据的时候 需要用reactive 进行转换
优缺点?

8 组合API toRef函数

目标:掌握使用toRef函数转换响应式对象中某个属性为单独响应式数据, 并且值是关联的。

toRef 是什么?
他是一个函数
有什么用?
它可以转换 响应式对象 中 某个 属性为单独响应式数据,并且 值是关联的
怎么用?
// 定义响应式对象
let obj = reactive({
      name: "张三",
      age: 18,
    });
    let name = toRef(obj, "name");
// 抽离响应式数据 (抽离不代表解除关联)
// 这个时候可以将对象的某个属性 转为 一个响应式对象 注意是对象
let name = toRef(obj, "name");
// 修改数据 value是存放值的地方
name.value = 5555;
为什么要用?
当我们定义了一个响应式对象 ,我们恰好在页面中只想使用它的一个属性,这个时候我们通过解构赋值,得到的属性并不是响应式的,如果想要该属性为响应式,需要我们通过toRef转换为响应式的,并且关联原有的数据。
注意:这个时候直接通过ref转为响应式数据也是可以的,但是会失去与原有数据的关联性,他将是一个全新的响应式数据,与原有对象无关!
使用场景?
有一个响应式对象数据,但是模板中 只需要使用其中一项数据

注意:从响应式数据对象中结构的数据,不再是响应式数据了

9 组合API toRefs 函数

目标:掌握使用toRefs函数定义转换响应式中所有属性为响应式数据 通常用于结构 | 展开reactive定义的对象

toRefs 是什么?
他是一个函数
有什么用?
它可以 转换 响应式对象 中所有属性为单独响应式数据 对象成为普通对象
怎么用?
// 定义响应式数据
let obj1 = reactive({
      name1: "reactive name",
      age1: 18,
    });
// 调用refs 函数 将对象的每一项都转为响应式数据
// 此时 obj1 和 obj3 是有关联的
let obj3 = toRefs(obj1); // 接受的参数为reactive对象
// 修改的时候需要注意 
// 可以直接修改 obj1
obj.name1 = '修改啦'
// 也可以修改包装之后处理的对象 但是 因为是响应式对象 他的值存在value中 
obj3.name1.value = "修改啦";
// 导出
return{
    // 记得导出转换之后的对象 
    ...obj3 
    // 模板中可以直接使用属性 而不用通过对象. 的方式进行调用
}

// 注意 如果 toRefs 接受的是一个普通对象 
// 也可以将这个对象的所有属性转为响应式的 不过 此时原有数据并不是响应式的,通过toRefs 处理之后的数据是响应式的
为什么要用?

使用场景?
剥离响应式对象 想使用响应式对象中的多个或者所有属性作为响应式数据

10 组合API ref函数

目标:掌握使用ref函数定义响应式数据,一般用于简单类型数据

ref 是什么?
他是一个函数
有什么用?
通常用于 简单数据类型定义为响应式数据
怎么用?
//ref() 通常接受一个普通数据类型
//	    返回值为一个响应式数据
//修改的时候 :
//一定要通过 .value 对响应式数据进行修改
//在模板中是用ref申明的响应式数据 可以省略.value
const num = ref(5)
num.value = 10
// ref 也可以接受一个 复杂数据类型 其内部会调用reactive函数
const ref = ref({
    name:"666"
})
// 当对未来要定义的响应式数据 类型是未知的
const data = ref(null)
为什么要用?
原生vue 不支持响应式数据 我们如果需要使用响应式数据 必须对原有数据进行转化
使用场景?
// 1.当你明确知道 需要的一个响应式数据是 对象 那么就是用reactive即可
// 2.其他情况下使用ref

11 组合API computed函数

目标:掌握使用computed 函数定义计算属性

什么是computed?
计算属性是用来计算数据的函数
有啥用呢 ?
computed 是用来定义计算属性的 计算属性不可以修改 
是一个函数 在vue2.x 是一个选项
怎么用呢?
// 用法1 - 普通用法 传函数
 const age = ref(18);
 const newAge = computed(() => {
      // 该函数的返回值 就是计算属性的值
      return age.value + 2;
 });
 return {
      age,
      newAge,
 };
注意:
1. vue3计算属性是可以多次调用的
2. 计算属性接收一个回调函数 return的值 就是计算属性的值
3. 计算属性是可以进行缓存的 当依赖的响应式数据未发生改变的时候 ,计算属性会返回上次计算的结果.
4. 计算属性默认是只读的,要想实现双向数据绑定,可以传一个对象进去
// 用法2 - 高级用法 传对象
const newAge = computed({
      // get 函数 获取计算属性的值
      get() {
        return age.value + 2;
      },
      // set 函数 当你给计算属性设置值的时候触发 监听计算属性值得改变
      set(value) {
        age.value = value - 2;
      },
    });
// 这样就实现了双向数据绑定的用法
使用场景?
1. 当你需要以来一个现有的响应式数据,根据一定逻辑得到一个新的数据
优缺点?

12 组合API watch函数

目标:掌握使用watch函数定义侦听器

定义计算属性:
watch 函数,用来定义侦听器的

// vue3 监听复杂数据类型 对象的时候 默认开启深度监听 
// 但是 任然无法监听到oldvalue
监听ref 定义的响应式数据 
const count = ref(0);
    const add = () => {
      count.value++;
    };
    // 当需要监听数据的变化 需要使用ref
    // 1. 监听一个ref数据
    // 1.1 第一个参数 需要监听的目标
    // 1.2 第二个参数 改变后的回调函数
    watch(count, (newVal, oldVal) => {
      console.log(newVal, oldVal);
    });
监听多个响应式数据变化
// 监听多个响应式数据 数组形式
    watch([count, obj], () => {
      console.log("count或者obj改变啦");
    });

监听reactive定义的响应式数据
// 直接监听
  const obj = reactive({
      name: "la",
      age: 18,
      info: {
        msg: "lalal 我是里层的对象",
      },
    });
    const mdName = () => {
      obj.name = 888;
    };
    const mdMsg = () => {
      obj.info.msg = 888;
    };
    watch(obj, (newVal, oldVal) => {
      console.log("obj数据改变了~");
    });
监听reactive定义的响应式数据 某一个属性 默认开启深度监听
 // 监听 reactive 中的某个属性,要用回调函数返回值形式
    watch(
      () => obj.name,
      () => {
        console.log("监听obj.name 的变化");
      }
    );
深度监听 监听reactive 定义的响应式对象的对象属性
要监听对象的某个属性的时候 如果该属性不是对象的话,是默认开启深度监听的
如果需要坚挺的这个属性又是一个对象的时候 这个时候 是无法监听到 这个对象属性的 需要开启深度监听
const obj = reactive({
      name: "la",
      age: 18,
      info: {
        msg: "lalal 我是里层的对象",
      },
    }); 
watch(
      () => obj.info,
      () => {
        console.log("obj.info.msg 改变啦");
      },
      {
        deep: true,
      }
    );

13 组合API ref属性

目标 :掌握使用ref属性绑定DOM或组件

获取DOM 或组件实例 可以使用ref属性 写法与vue2.0需区分开


获取单个DOM 或 组件
  // 1. 定义以一个空的响应式数据 ref定义的
  // 2. setup 中返回该数据 想获取那个DOM 在该元素上使用ref属性绑定该数据即可
    const box = ref(null);
    console.log(box);
    return {
      box,
    };
<template>
	<div ref="box">我是box</div>
</template>	
获取v-for 遍历的DOM 或组件
 // 2 获取v-for 遍历的元素
 // 2.1 定义一个空数组 接收所有的li
 // 2.2 定义一个函数 往空数组中pushDOM
    const list = [];
    const setDom = (el) => {
      console.log("setDOM");
      list.push(el);
      console.log(list);
    };
<template>
	 <ul>
      <li v-for="i in 4" :key="i" :ref="setDom">{{ i }}</li>
    </ul>
</template>	

总结:

  • 单个元素 :先申明ref响应式数据 返回给模板 通过ref绑定数据
  • 遍历的元素:先定义一个空数组(非响应式)定义一个函数获取元素 返回给模板使用 通过ref绑定这个

14 组合API 父子通讯

目标:掌握使用props 选项和emits选项完成父子通讯

父传子
// 父组件

setup() {
    const count = ref(0);
    return {
      count,
    };
  },
// 子组件
// 和vue2.x 一样 正常接收数据
  props: {
    count: {
      type: Number,
      default: 0,
    },
  },
  // 如果想要在setup函数中使用数据 可以直接传参 props
  setup(props) {
    console.log(props);
  },
子传父
// 子组件

// 第一个参数为props 第二个参数为context 
// context 中有emit方法
 setup(props, context) {
    // 获取父组件传来的值
    console.log(props);
    // 向父组件传值
    const changeMoney = () => {
      // 消费50 元
      // 通知父组件 money需要变成50
      context.emit("change-money", 50);
    };
    return {
      changeMoney,
    };
  },
// 父组件
  

我是父组件里

{{ count }}


setup() { const count = ref(100); const updateMoney = (money) => { count.value -= 50; }; return { count, updateMoney, }; },

拓展:

  • 在vue2.x 的时候 .sync 除去v-model的情况下实现双向数据绑定的另外一种方式

     
    

    简写:

     
    
  • 在vue 3.0 的时候 使用v-model:money=“money” 即可

    // 父组件 
    
    // 子组件
      const changeMoney = () => {
          // 消费50 元
          // 通知父组件 money需要变成50
          context.emit("update:count", 50);
        };
    

总结:

  • 父传子:在setup 中使用props 数据,接受的第一个参数就是

  • 子传父:触发自定义时间的时候 emit 来自setup的第二个参数 context对象

  • 在vue2.x 中 v-model 和 .sync 已经和并成 v-model 指令

15 组合API 依赖注入

目标:掌握使用provide函数和inject函数完成后代组件通讯

使用场景: 有一个父组件 有很多后代组件 都需要共享父组件的数据
//父组件
  setup() {
    const money = ref(1000);
    const changeMoney = (val) => {
      console.log("changeMoney");
      money.value -= 50;
    };
    // 将数据提供给后代组件 provide
    provide("money", money);
    // 将修改数据的函数给后代组件
    provide("changeMoney", changeMoney);

    return {
      money,
    };
  },
// 后代组件接收数据
setup() {
    const money = inject("money");
    const changeMoney = inject("changeMoney");
    // 孙组件 消费50 通知父组件App 进行修改
    // 不能自己修改数据 遵循单项数据流  在哪定义在那修改
    const fn = () => {
      changeMoney(50);
    };
    return {
      money,
      fn,
    };
  },

总结:

  • provide 函数提供数据和修改数据的函数给后代组件(单项数据流)
  • inject函数给当前组件注入provide 提供的数据和函数

16 v-model 语法糖

目标 掌握vue3 的 v-model 的语法糖原理

在 vue 2.0 中 v-model 语法糖 简写


在vue 3 中v-model 语法糖有所调整

<Son :modelValue="msg" @update:modelValue="msg=$event"/>
    
//父组件

  <!--  <Son :modelValue="count" @update:modelValue="count = $event"> </Son>-->
  <!--  简写-->
  <Son v-model="count"></Son>

// 子组件
  setup(props, { emit }) {
    const fn = () => {
      console.log("fn");
      // 改变数据
      emit("update:modelValue", 100);
    };
    return { fn };
  },

17-mixins 语法

目标: 掌握mixins 语法的基本使用 Vue2.x 封装逻辑的方式 Vue3.0 建议使用组合式API

官方解释:

  • 混入(mixins)提供了一种非常灵活的方式,来分发Vue组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入时,所有混入对象的选项将被"混合"进入组件本身的选项

理解全局混入:所有组件混入了这些逻辑代码

// vue 2 
Vue.mixin({ 选项 })
// vue 3
app.mixin({
 	选项
})

总结:在vue2.0 中一些可复用逻辑可以用mixins来封装,但是需要考虑逻辑代码冲突的问题。 vue3.0 的组合API很好的解决了这个问题 ,就不再推荐使用mixins了

你可能感兴趣的:(vue,vue.js,前端,javascript)