深海 深海
首页
  • 随手笔录
  • 电影
  • 音乐
  • 书籍
汇总
面试
  • 开发工具
  • VScode插件
  • Git
  • Mac时代
  • 前端工具
  • Chrome
  • HTML
  • CSS
  • Javascript
  • Typescript
  • Axios
  • 框架

    • Vue
    • uni-app
  • Nginx
  • Linuk
事例
关于

深海

人生如逆旅,我亦是行人
首页
  • 随手笔录
  • 电影
  • 音乐
  • 书籍
汇总
面试
  • 开发工具
  • VScode插件
  • Git
  • Mac时代
  • 前端工具
  • Chrome
  • HTML
  • CSS
  • Javascript
  • Typescript
  • Axios
  • 框架

    • Vue
    • uni-app
  • Nginx
  • Linuk
事例
关于
  • HTML
  • CSS的奥秘

  • JavaScript

  • TypeScript

  • Vue

    • 介绍
    • 基础
    • Vuex
    • Vue-Router
    • Vue-CLI
    • Vue3
      • Vue3.0 工程
        • Vue-cli 创建
        • Vite 创建
      • 生命周期
      • 组合式 API
        • 生命周期钩子函数
        • setup
        • 核心
        • ref()
        • computed()
        • reactive()
        • ref 与 reactive 区别
        • watch() - 监听函数
        • watchEffect()
        • 工具
        • toRef 与 toRefs
        • hook 函数
        • provide 与 inject
        • shallowReactive 与 shallowRef
        • readonly 与 shallowReadonly
        • toRaw 与 markRaw
        • customRef 自定义 ref
        • 判断响应式数据
        • isRef()
        • isReactive()
        • isReadonly()
        • isProxy()
        • Composition API 的优势
    • 项目搭建
    • Vue3

  • uni-app

  • 前端
  • Vue
深海
2023-05-30
目录

Vue3

# Vue3.0 工程

# Vue-cli 创建

# 查看@vue/cli版本,保证@vue/cli版本在4.5.0以上
vue --version
vue -V
# 安装或者升级@vue/cli
npm install -g @vue/cli
# 创建项目
vue create <project-name>
# 启动
cd <project-name>
npm run serve
1
2
3
4
5
6
7
8
9
10

# Vite 创建

npm init vite-app my-vue3-project
npm init vite@latest my-vue3-project
1
2

# 生命周期

image

# 组合式 API

# 生命周期钩子函数

onBeforeMount; /* 在组件被挂载之前被调用 */
onMounted; /* 在组件挂载完成后执行 */
onBeforeUpdate; /* 在组件即将因为响应式状态变更而更新其 DOM 树之前调用  */
onUpdated; /* 在组件因为响应式状态变更而更新其 DOM 树之后调用  */
onBeforeUnmount; /* 在组件实例被卸载之前调用  */
onUnmounted; /* 在组件实例被卸载之后调用  */
1
2
3
4
5
6

# setup

  • 是所有的Composition API(组合 API)
  • 组件中所用到数据方法等均要配置在 setup 中
  • setup 两种返回值
    • 返回对象
    • 返回渲染函数
  • setup 的参数
    • props 值为对象,包含外部传递过来,且组件内部声明接收了的属性
    • context 上下文对象
      • attrs 值为对象,包含组件外部传递过来,但没有在 props 配置中声明的属性,相当于 v2 中的 this.$attrs
      • slots 收到的插槽内容,相当于 this.$slots
      • emit 分发自定义事件的函数,相当于 this.$emit
setup(props,context){
  let title = 'hello';
  // 对象返回
  return{
    title,
  }
  // 渲染函数
  return ()=>h('h1','hello')
}
1
2
3
4
5
6
7
8
9

注意

  1. Vue2 配置(data,methods,computed 等)中可以访问到 setup 中的属性,方法
  2. setup 中不能访问 Vue2 配置(data,methods,computed...)
  3. 如果 Vue2 和 Vue3 中有重名,setup 优先
  4. setup 不能是一个 async 函数,因为返回值不是 return 对象,而上一个 Promise
  5. setup 在 beforeCreate 之前执行一次,this 时 undefined

# 核心

# ref()

定义一个响应式的数据

说明

  • 接受的数据可以是基本类型,也可以是对象类型
  • 基本类型的数据:响应式依然是靠Object.defineProperty()的get与set完成的
  • 对象类型的数据:内容使用了 Vue3.0 中的一个新函数reactive函数
  • 模版中使用不需要.value :::
<script>
import { ref } from "vue";
export default {
  name: "App",
  data() {
    return {};
  },
  setup() {
    let city = ref("北京");
    function change() {
      city.value = "上海";
    }
    return {
      city,
    };
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# computed()

import { computed } from "vue";
export default {
  setup() {
    let person = reactive({
      firstName: "张",
      lastName: "三",
    });
    // 只读写法
    person.getName = computed(function () {
      return person.firstName + "-" + person.lastName;
    });
    // 完整写法(读和写)
    person.getName = computed({
      get() {
        return person.firstName + "-" + person.lastName;
      },
      set(value) {
        // 赋值
        person.firstName = value.split(",")[0];
      },
    });
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# reactive()

定义一个对象类型的响应式数据

说明

  • reactive接受一个对象或数组,代理对象(Proxy 的实例对象)
  • reactive 定义的对象是深层次的
  • 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作
<script>
import { reactive } from "vue";
export default {
  name: "App",
  data() {
    return {};
  },
  setup() {
    let citys = reactive(["北京", "上海", "广州", "深圳"]);
    function change() {
      citys[0] = "杭州";
    }
    return {
      citys,
    };
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# ref 与 reactive 区别

  • 定义数据角度对比
    • ref 用来定义:基本类型数据
    • reactive 用来定义:对象或数组类型数据
    • 注意 ❗️ :ref 也可以用来定义对象或数组类型数据,内部会自动通过reactive转为代理对象
  • 从原理角度对比
    • ref 通过Object.defineProperty()的 get 与 set 来实现响应式(数据劫持)
    • reactive 通过使用Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据
  • 从使用角度对比
    • ref 定义的数据:操作数据需要.value,读取数据时模版直接读取,不需要.value
    • reactive 定义的数据:操作数据与读取数据都不需要.value

# watch() - 监听函数

需要指明监视的属性,也要指明监视的回调

import { ref, reactive, watch } from "vue";
export default {
  setup() {
    /**
     * {immediate:true,deep:true}
     * immediate:true  在第一次进入页面时就会监听
     * deep  用来深度监听
     */
    // 1.监听ref中定义的一个数据
    watch(a, (newVal, oldVal) => {});
    // 2.监听ref中多定义的所有ref数据
    watch([a, d], (newVal, oldVal) => {});
    // 3.监听reactive所定义的一个响应式数据中的全部数据
    /**
     * 1. 无法正确的获取oldVal(若需要获取oldVal,需要将属性设置到ref函数中)
     * 2. 强制开启深度监听默认deep:true 设置deep:false无效
     */
    watch(c, (newVal, oldVal) => {}, { deep: false });
    // 4.监听reactive所定义的一个响应式数据中的某个数据
    watch(
      () => b.num,
      (newVal, oldVal) => {}
    );
    // 5.监听reactive所定义的一个响应式数据中的某些数据
    watch([() => b.age, () => b.num], (newVal, oldVal) => {});
    // 6.监视reactive所定义的对象中的某个属性(对象),需要设置deep:true,否则监视不到
    watch(
      () => b.work,
      (newVal, oldVal) => {},
      { immediate: true, deep: true }
    );
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# watchEffect()

不用指明监视哪个属性,回调中用到哪个属性,就监视哪个属性,只要回调中用到的数据发生变化,则直接重新执行回调

watchEffect(() => {});
1

# 工具

# toRef 与 toRefs

作用为将响应式中的对象某个属性单独提供给外部使用

  • 创建一个 ref 对象,其中的 value 值指向另一个对象中的某个属性
  • toRef创建单个 ref 对象,toRefs批量创建多个 ref 对象
const x = toRef({}, "属性");
const x = toRefs({});
1
2

# hook 函数

本质是一个函数,把 setup 中使用的 Composition API 进行了封装,类似于 Vue2 中的 mixin

  • 创建模块文件
import { reactive, onMounted, onBeforeUnmount } from "vue";
export default function () {
  let ponent = reactive({
    x: 0,
    y: 0,
  });
  function savepon(event) {
    ponent.x = event.pageX;
    ponent.y = event.pageY;
  }
  onMounted(() => {
    window.addEventListener("click", savepon);
  });
  onBeforeUnmount(() => {
    window.removeEventListener("click", savepon);
  });
  return ponent;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  • 引入
import userPon from "../hooks/userpon";
export default {
  setup() {
    let ponent = userPon();
    return {
      ponent,
    };
  },
};
1
2
3
4
5
6
7
8
9

# provide 与 inject

provide()提供一个值,可以在应用中的所有后代组件中注入使用。用于实现祖组件与后代组件间的通信

// 祖组件
import { provide } from 'vue'
export default {
  setup(){
    provide('message','hello')
  }
}
// 后代组件
import { inject } from 'vue'
export default {
  setup(){
    // 使用inject接收,后代组件接收的是Proxy格式,是响应式
    const x = inject('message')
    return {x}
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • 创建 hooks 文件
import { reactive, onMounted, onBeforeUnmount } from "vue";
export default function () {
  let point = reactive({
    x: 0,
    y: 0,
  });
  function savePoint(event) {
    point.x = event.pageX;
    point.y = event.pageY;
  }
  onMounted(() => {
    window.addEventListener("click", savePoint);
  });
  onBeforeUnmount(() => {
    window.removeEventListener("click", savePoint);
  });
  return point;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  • 引用
import usepoint from "./usepoint.js";
export default {
  setup() {
    const point = usepoint;
    return { point };
  },
};
1
2
3
4
5
6
7

# shallowReactive 与 shallowRef

  • shallowReactive: 只处理对象最外层属性的响应式(浅响应式)。
  • shallowRef: 只处理基本数据类型的响应式, 不进行对象的响应式处理
  • 使用场景
    • 一个结构对象,有多层结构,但只是最外层属性变化 (shallowReactive)
    • 一个结构对象,后续不会修改对象中的属性,而是生成新的对象来替换 (shallowRef)

# readonly 与 shallowReadonly

  • readonly让一个人响应式数据变为只读(深只读)。
  • shallowReadonly让一个响应式数据变为只读(浅只读,对象中嵌套的多层结构可以修改)
import { readonly, shallowReadonly } from "vue";
export default {
  setup() {
    let per = reactive({
      name: "东",
      age: 20,
      work: {
        num: {
          games: 100,
        },
      },
    });
    // 深只读
    let person = readonly(per);
    // 浅只读
    let person = shallowReadonly(per);
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# toRaw 与 markRaw

  • toRaw
    • 作用:将一个由reactive生成的响应式对象转为普通对象
    • 场景:用于读取响应式对象对应的普通对象,对其所有操作,不会引起页面更新
  • markRaw
    • 作用: 标记一个对象,使其永远不会再成为响应式对象
    • 场景:
      1. 复杂的第三方库
      2. 渲染具有不可变数据的大列表,跳过响应式转换可以提高性能

# customRef 自定义 ref

创建一个自定义的 ref,显式声明对其依赖追踪和更新触发的控制方式。

import { customRef } from "vue";
export default {
  setup() {
    function useDebouncedRef(value, delay = 200) {
      let timeout;
      return customRef((track, trigger) => {
        return {
          get() {
            track(); // 通知vue去跟踪value大变化
            return value;
          },
          set(newValue) {
            clearTimeout(timeout);
            timeout = setTimeout(() => {
              value = newValue;
              trigger(); // 通知Vue重新解析模版
            }, delay);
          },
        };
      });
    }
    const x = useDebouncedRef("hello");
    return {
      x,
    };
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 判断响应式数据

# isRef()

判断一个值是否为一个 ref 对象

# isReactive()

检查一个对象是否是由reactive创建的响应式代理

# isReadonly()

检查一个对象是否是由readonly创建的只读代理

# isProxy()

检查一个对象是否是由reactive或者readonly方法创建的代理

# Composition API 的优势

  • Options API 问题

使用传统 Options API 当数据复杂时,新增或修改一个需求,就需要在各个函数里面进行修改

  • Composition API

通过 hook 函数将各功能模块拆分出去,增强代码的可维护性

2.x 全局 API 3.x 实例 API
Vue.config.xxx app.config.xxx
Vue.congig.productionTip 移除
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use
Vue.prototype app.config.globalProperties
上次更新: 2025/02/27, 19:02:07
Vue-CLI
项目搭建

← Vue-CLI 项目搭建→

最近更新
01
TypeScript是什么
06-15
02
项目搭建
05-21
03
Prettier
02-27
更多文章>
Theme by Vdoing | Copyright © 2022-2025 京ICP备2020044002号-4 京公网安备11010502056618号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式