vue-3

项目创建

创建一个 Vue 应用 npm create vue@latest 根据提示选择自己想要的项目

用 npm 安装

https://cn.vuejs.org/guide/quick-start.html#creating-a-vue-application

选择: TS、 Vue Router、 Pinia、 ESlint 、 Prettier

  • 开启 "typescript.validate.enable": true, 用户设置,eslint 即可生效

基础语法

  • Vue Class Component :使用类的形式写 vue 组件 地址open in new window

  • 组件不强制要求唯一跟标签

  • 编写组件引入时 会报 TS6307 重启一下编辑器就好

  • 只需要安装 Sass 包 才能正常使用 sass

  • app.component('SomeName', SomeComponent) 名称用大驼峰 使用时可以用 <SomeName/> <some-name/>

引入一些类型

import type { CSSProperties } from 'vue' // css 属性

周期函数

https://v3.cn.vuejs.org/guide/composition-api-lifecycle-hooks.html

Hooks 和 Mixins

mixins 的缺点: 1. 数据来源不明,因为是隐式传入,没有显示的调用,都是传进来后自动挂载; 2. 同名的数据和方法问题 3. minins 和组件是多对多的关系,会导致定位问题异常复杂

hooks 可以独立抽取为方法,封装 CompositionAPI,然后各地方独立引用


composition API 组合式 API

获取元素

<!-- 这里ref的值和下面返回的值要一致 -->
<div ref="myRef">ref</div>
import { ref, getCurrentInstance } from 'vue';

setup() {
    const myRef = ref(null);
    // myRef.value // 返回DOM

    const { proxy } = getCurrentInstance();
    proxy.myRef // 返回DOM

    return myRef
}

setup

  • 在 beforCreate 之前执行,并且替换了 beforCreate created 周期函数

  • 返回值:

    1. 对象(对象的属性、方法,在模板中可以直接使用)
    2. 函数(定义渲染内容) 参考下方示例
import { defineComponent, ref, h } from "vue";
export default defineComponent({
  setup(props) {
    /**
     * props 使用时不要直接用es6的解构,如果要用,可以用 toRefs 处理后解构 组件外部传递进来 且组件内部声明接收了的属性
     * context  上下文对象
     * context.attrs 组件外部传入的 没有在 props 配置中声明的属性,相当于 this.$attrs
     * context.slots 相当于 this.$slots
     * context.emit 相当于 this.$emit
     */
    const value = ref(0);
    /* 返回一个对象 */
    return {
      value,
    };

    /* 返回一个渲染函数, 模板内容会被全部替换为该内容 */
    // return () => h('pre', 'code pre')
  },
});
setup 语法糖
// 组件直接引入,可以直接使用
import { defineProps } from "vue"; // 定义 props
defineProps({
  info: {
    type: String,
    default: "",
  },
});
  • reactive() 创建响应数据 类似原来的 data 数据
ref()

目的是让一些定义的基本数据类型,可以成为响应式的数据

基本数据类型,响应式依然使用的是 Object.defineProperty() 返回的是 refImpl (reference implement) 引用实现的实例对象,通俗的叫法是 引用对象

对象类型数据:响应式采用 reactive; ref(obj) 等价于 reactive({value: obj}),原理是采用 Proxy 拦截 然后 使用 Reflect 对属性进行操作

当挂载到 reactive() 上时,会自动把响应式数据对象展开为原始的值,不需通过 .value 就可以直接被访问

vue 模板中使用可以不加 .value 访问, js 代码中通过 .value 获取变量值

用 isRef 来判断是否是 ref() 创建的值

reactive()

定义对象的响应式数据 (无法处理基本类型)

原理是使用 Proxy 代理拦截,所以利用下标修改数组 也可以被监听到

可直接获取对象属性


  • toRefs()

将 reactive() 创建出来的响应式对象,转换为每个属性节点都是 ref() 类型的响应式数据

  • 返回 state 时 如果要解构对象,需要用 toRefs 处理一下
computed() 函数

用来创建计算属性,返回值是一个 ref 的实例

import { computed, ref } from "vue";
const count = ref(0);
// 只读
const add = computed(() => count.value + 1);
// 可读 可赋值
const addPlus = computed({
  get() {
    return count.value;
  },
  set(val) {
    count.value = val;
  },
});
// 可赋值的使用
addPlus.value = addPlus.value + 4;
provide() 和 inject()

可以实现嵌套组件之间的数据传递。在 setup() 函数中使用。父级组件中使用 provide() 函数向下传递数据;子级组件中使用 inject() 获取上层传递过来的数据。

watchEffect | watch
/**
 * 1. 立即执行 2. 可以停止监听 3. 会自动收集依赖 4.只能监听某个值,不能监听对象  5. 不能获取oldvalue newvalue
 * 6. 内部可以有异步操作
 */
const stop = watchEffect(() => {
  console.log(count.value);
});
const handleAdd = () => {
  count.value++;
};
// stop
const handleStop = () => {
  stop(); // 监听不再有效
};

/**
 * 第一个参数可以为以下
 * 第二个参数为回调函数
 * 第三个参数可以为:immediate deep
 * 参考: https://cn.vuejs.org/api/reactivity-core.html#watch
 */
// 1. 一个函数返回一个值:一般用于监听 reactive 的属性,因为不能直接监听reactive属性,所以采用函数返回值的形式
const re = reactive({ count: 1 }); // 触发:re.count = 2
/* 监听 props 值,如 re.count 替换成 props.someKey */
watch(
  () => re.count,
  (newVal, oldVal) => {
    console.log("watch", newVal, oldVal);
  }
);
// 2. 侦听源是一个 ref:
const rf = ref(0); // 触发:rf.value = 1
watch(rf, (newVal, oldVal) => {
  console.log("rf watch:", newVal, oldVal);
});
// 3. 直接监听响应式对象,侦听器自动处于深层级模式,注意无法得到旧值
const re = reactive({ count: 1 }); // 触发:re.count = 2
watch(re, (newVal, oldVal) => {
  console.log("re watch:", newVal, oldVal);
});
// 4. 当使用函数作源时,只在此函数的返回值发生变化时才会启动。需要明确地用 { deep: true } 才能进入深层级模式
// const re = reactive({ count: 1 }) // 触发:re.count = 2
watch(
  () => re,
  (newVal, oldVal) => {
    console.log("re watch:", newVal, oldVal);
  },
  { deep: true }
);
// 5. 一个数组
const re = reactive({ count: 1 });
const rf = ref(0);
watch(
  [re, rf],
  ([ren, rfn], [reo, rfo]) => {
    // 第一个数组全是新值,第二个数组全是旧值
    console.log("re rf", ren, rfn, reo, rfo);
  },
  { deep: true }
);
Last Updated:
Contributors: Warren