【Vue3】整理的一些Vue3知识点和案例(Vue3 获取窗口宽和高)

【Vue3】整理的一些Vue3知识点和案例(Vue3 获取窗口宽和高)


在这里插入图片描述

1- Vue3基础介绍

1.1 Vue3简介

  • 2020年9月18日,Vue.js发布3.0版本,代号:One Piece(海贼王)
  • Vue3.0使用了 Typescript 进行了大规模的重构,带来了 Composition API RFC 版本,类似 React Hook 一样的写 Vue,可以自定义自己的 hooks

1.2 与Vue2的不同

1.启动方式不同

在main.js 里

  • Vue3
## Vue3

import {
    
     createApp } from "vue";
createApp(App).use(store).use(router).mount('#app')
  • Vue2
## Vue2
import Vue from "vue";
new Vue({
    
    
router,
store,
render: (h) => h(App),
}).$mount("#app");
2.全局挂载方法不同
  • Vue3
// Vue3

const app = createApp(App);
//定义vue3 的全局方法,config 配置,global 全局 Properties属性
app.config.globalProperties.$say = function (msg) {
    
    
alert(msg);
};
  • Vue2
// Vue2

Vue.prototype.$say=function(msg){
    
    alert{
    
    msg}}
3.根节点不同
  • vue3 可以有多个根节点
  • vue2 只能有一个根节点
4.生命周期里不同
  • Vue3

在这里插入图片描述

  • Vue2

在这里插入图片描述

1.3 Vue3特点

  • 新增 组合式 API
  • 更加接近原生js
  • 按需加载

1.4 Vue3带来了什么

1.性能的提升
  • 打包大小减少41%

  • 初次渲染快55%, 更新渲染快133%

  • 内存减少54%

2.源码的升级
  • 使用Proxy代替defineProperty实现响应式

  • 重写虚拟DOM的实现和Tree-Shaking

3.拥抱TypeScript
  • Vue3可以更好的支持TypeScript
4.新的特性
  1. Composition API(组合API)
    • setup配置
    • refreactive
    • watchwatchEffect
    • provideinject
  2. 新的内置组件
    • Fragment
    • Teleport
    • Suspense
  3. 其他改变
    • 新的生命周期钩子
    • data 选项应始终被声明为一个函数
    • 移除keyCode支持作为 v-on 的修饰符

2- Vue3基础工作

## 安装 vue-cli
npm install -g @vue/cli

## 创建一个项目
## 使用create 命令行创建

vue create 项目名

在这里插入图片描述

3- 常用 Composition API


3.1 setup

  • setupVue3.0 中一个新的配置项,值为一个函数

  • setup是 Composition API(组合API) 的入口

  • 组件中所用到的:数据、方法等等,均要配置在setup

  • setup函数的两种返回值:

    • 若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)
    • 若返回一个渲染函数:则可以自定义渲染内容。(了解)
  • 注意点:

1.尽量不要与Vue2.x配置混用

  • Vue2.x配置(data,methods,computed...)中可以访问setup中的属性、方法
  • 但在setup不能访问Vue2.x配置(data,methods,computed...
  • 如果有重名, setup优先

2.setup不能是一个async函数,因为返回值不再是return的对象, 而是promise, 模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)

3.2 ref函数

  • 作用:定义一个响应式的数据
  • 语法:
##语法
const xxx = ref(initValue)
  1. 创建一个包含响应式数据的引用对象(reference对象,简称ref对象)
  2. js 中操作数据:xxx.value
  3. 模板中读取数据:不需要.value,直接
    { {xxx}}
  • 备注
  1. 接收的数据可以是:基本类型、也可以是对象类型。
  2. 基本类型的数据:响应式依然是靠Object.defineProperty()getset完成的。
  3. 对象类型的数据:内部 “ 求助 ” 了Vue3.0中的一个新函数—— reactive函数。

3.3 reactive函数

  • 作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
  • 语法
##语法
const 代理对象 = reactive(源对象)

接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象

  • reactive 定义的响应式数据是 “深层次的”

  • 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。

3.4 reactive对比ref

  • 从定义数据角度对比
  1. ref 用来定义 基本类型数据
  2. reactive 用来定义 对象(或数组)类型数据
  3. 备注: ref 也可以用来定义 对象(或数组)类型数据,它内部会自动通过 reactive 转为代理对象
  • 从原理角度对比:
  1. ref 通过 object.defineProperty()getset 来实现响应式(数据劫持)
  2. reactive 通过使用 Proxy 来实现响应式(数据劫持),并通过 Reflect 操作 源对象内部的数据
  • 从使用角度对比
  1. ref 定义的数据:操作数据 需要 .value,读取数据时模板中直接读取不需要 .value
  2. reactive 定义的数据:操作数据与读取数据:均不需要 .value

3.5 setup的两个注意点

setup 执行的时机
  • 在beforeCreate 之前执行一次,this 是 undefined
setup 的参数
  • props :值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性
  • context:上下文对象
    • attrs:值为对象,包含:组外部传递过来,但没有在props配置中声明的属性,相当于 this.$attrs
    • slots:收到的插槽内容,相当于 this.$slots
    • emit:分发自定义事件的函数,相当于this.$emit

3.6 计算属性与监视

1.computed
  • 与Vue2.x中computed配置功能一致
  • 写法
import {
    
    computed} from 'vue'

setup(){
    
    
    ...
	//计算属性——简写
    let fullName = computed(()=>{
    
    
        return person.firstName + '-' + person.lastName
    })
    //计算属性——完整
    let fullName = computed({
    
    
        get(){
    
    
            return person.firstName + '-' + person.lastName
        },
        set(value){
    
    
            const nameArr = value.split('-')
            person.firstName = nameArr[0]
            person.lastName = nameArr[1]
        }
    })
}
2.watch函数

在这里插入图片描述

  • 与Vue2.x中watch配置功能一致
  • 两个小“坑”:
  1. 监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)。
  2. 监视reactive定义的响应式数据中某个属性时:deep配置有效。
//情况一:监视ref定义的响应式数据
watch(sum,(newValue,oldValue)=>{
    
    
	console.log('sum变化了',newValue,oldValue)
},{
    
    immediate:true})

//情况二:监视多个ref定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{
    
    
	console.log('sum或msg变化了',newValue,oldValue)
}) 

/* 情况三:监视reactive定义的响应式数据
			若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue!!
			若watch监视的是reactive定义的响应式数据,则强制开启了深度监视 
*/
watch(person,(newValue,oldValue)=>{
    
    
	console.log('person变化了',newValue,oldValue)
},{
    
    immediate:true,deep:false}) //此处的deep配置不再奏效

//情况四:监视reactive定义的响应式数据中的某个属性
watch(()=>person.job,(newValue,oldValue)=>{
    
    
	console.log('person的job变化了',newValue,oldValue)
},{
    
    immediate:true,deep:true}) 

//情况五:监视reactive定义的响应式数据中的某些属性
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{
    
    
	console.log('person的job变化了',newValue,oldValue)
},{
    
    immediate:true,deep:true})

//特殊情况
watch(()=>person.job,(newValue,oldValue)=>{
    
    
    console.log('person的job变化了',newValue,oldValue)
},{
    
    deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效
3.watchEffect函数

在这里插入图片描述

  • watch的套路是:既要指明监视的属性,也要指明监视的回调。
  • watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
  • watchEffect有点像computed:
  1. 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
  2. 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{
    
    
    const x1 = sum.value
    const x2 = person.age
    console.log('watchEffect配置的回调执行了')
})

3.7 生命周期

在这里插入图片描述

  • Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:
beforeDestroy  改名为 beforeUnmount
destroyed 改名为 unmounted
  • Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:

在这里插入图片描述

3.8 自定义hook函数

  • 什么是hook?—— 本质是一个函数,把setup函数中使用的Composition API进行了封装
  • 类似于vue2.x中的mixin
  • 自定义hook的优势: 复用代码, 让setup中的逻辑更清楚易懂

3.9 toRef

  • 作用:创建一个 ref 对象,其value值指向另一个对象中的某个属性。

  • 语法:const name = toRef(person,'name')

  • 应用: 要将响应式对象中的某个属性单独提供给外部使用时。

  • 扩展:toRefstoRef功能一致,但可以批量创建多个 ref 对象,语法:toRefs(person)

3.10 setup语法糖

只需要在 script 标签中添加 setup,组件只需引入不用注册,属性和方法也不用返回,setup 函数也不需要,甚至 export default 都不用写了,不仅是数据,计算属性和方法,甚至是自定义指令也可以在我们的 template 中自动获得。

setup script 语法糖提供了三个新的API来供我们使用:definePropsdefineEmituseContext

  • defineProps 用来接收父组件传来的值props。
  • defineEmit 用来声明触发的事件表。
  • useContext 用来获取组件上下文context。

4- 案例

  • StepCom.vue
<template>
  <div>
    <button @click="count--">-</button>
    <input type="text" style="width: 80px" v-model="count" />
    <button @click="count++">+</button>
  </div>
</template>

<script setup>
//defineProps 定义props
import {
    
     defineProps, ref, watch, defineEmits, watchEffect } from "vue";
//定义props 传入参数
const props = defineProps({
    
    
  //类型为数字或者字符串,默认值为1
  value: {
    
    
    type: [Number, String],
    default: 1,
  },
});
//定义一个响应式对象初始值为props.value
const count = ref(props.value);

//定义事件发送器
var emits = defineEmits(["input"]);
//监听count的变化
watch(count, () => {
    
    
  //发送一个input事件,事件的值为count 的value
  emits("input", count.value);
});
//在 watchEffect 都会被自动监听,执行回调函数
/* 只要watchEffect中出现了数据,数据发生变化时候,都会执行watchEffect */
watchEffect(() => {
    
    
  count.value = props.value;
});
</script>

<style>
</style>
  • HomeView.vue
<template>
  <div>
    <button @click="num++">{
    
    {
    
     num }}</button> <br />
    <button @click="setNum(num + 5)">5</button> <br />
    <p v-for="item in list" :key="item">{
    
    {
    
     item }}</p>
    <input type="text" v-model="temp" @keyup.enter="addList()" />
  </div>
</template>

<script>
//1.ref 导入 一个创建响应式 值类型数据的方法
//2,reactive  响应式 引用类型的方法
import {
    
     ref, reactive } from "vue";
export default {
    
    
  setup() {
    
    
    //1.导入一个创建响应式,num的默认值是5
    const num = ref(5);

    //3.定义更新num的方法
    function setNum(n) {
    
    
      //在setup 中num 的值访问 与赋值 要加value  在template 不需要
      num.value = n;
    }

    /* 定义一个响应式列表数据 */
    var list = reactive(["Vue", "React", "Angular", "小程序"]);

    // 定义temp 临时数据
    var temp = ref("");
    //定义添加list 的方法
    function addList() {
    
    
      //注意值类型访问要加value
      list.push(temp.value);
      temp.value = "";
    }
    //2.返回num
    return {
    
     num, setNum, list, temp, addList };
    // console.log("setup在组件挂载前执行");
  },
  beforeUnmount() {
    
    
    console.log("组件将要卸载");
  },
  unmounted() {
    
    
    console.log("组件已经卸载");
  },
};
</script>

<style>
</style>

5- Vue3 获取窗口宽和高

  • 新建utils.js 文件
import {
    
     ref, onMounted, onBeforeUnmount } from "vue";
//导出获取窗口的宽高
export function useWinSize() {
    
    
    const size = ref({
    
     width: window.innerWidth, height: window.innerHeight });
    //窗口变化时候更新 size
    function onResize() {
    
    
        size.value = {
    
    
          //用窗口的最新宽高更新 width 与 height 
            width: window.innerWidth,
            height: window.innerHeight,
        };
    }
    //组件 挂载完毕 更新  size
    onMounted(() => {
    
    
        window.addEventListener("resize", onResize);
    });
    //组件 要卸载的时候移除 事件监听
    onBeforeUnmount(() => {
    
    
        window.removeEventListener("resize", onResize);
    });
    return size;
}

在这里插入图片描述

  • 在HomeView.vue 里 使用
<template>
  <div>
    <h1>setup</h1>
    <button @click="num++">{
    
    {
    
     num }}</button>
    <step-com :value="num" @input="num = $event" ref="stepper"></step-com>
    <p>{
    
    {
    
     size }}</p>
  </div>
</template>

<script setup>
// 使用setup 可以简写 ,不用导出组件不用注册了
import StepCom from "@/components/StepCom.vue";
import {
    
     onMounted, ref } from "vue";
import {
    
     useWinSize } from "@/utils/utils";
const num = ref(5);

const stepper = ref();
onMounted(() => {
    
    
  console.log("组件已经挂载完毕");
  //组件挂在完毕引用stepper组件
  /* stepper.value 就是对stepper-com组件的引用 */
  console.log(stepper.value.count);
});

const size = useWinSize();
</script>

<style>
</style>

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_59012240/article/details/127707654