Vue3新的api

1. composition api

1.1 data → ref / reactive

refreactive使得我们主动去包装那些会修改的数据,不变的则将原始对象交给模板;在Vue2中,为了能在模板中使用一些数据,我们通常将那些不变的数据也放在data里面,而Vue默认会为这些数据做响应式,所以就有了Object.freeze()这种优化手段。而这个问题在Vue3中就不用担心了

import { ref, reactive } from "vue";
const type = ref("order"); 
const pageInfo = reactive({
  pageIndex: 0,
  pageSize: 20,
});

// methods:直接声明成一个函数
const change = function (e, num) {
  pageInfo.pageSize = num;
  type.value = "task"; // ref包装的在读取时要使用.value,在模板中不需要
};

ref包装原始类型,会被包装成一个RefImpl实例,劫持value属性。用reactive包装引用类型,返回一个Proxy代理对象

image.png

image.png

image.png

1.2 props

  • options写法
export default {
  props: {
    pageType: {
      type: String,
      default: "task",
    },
    taskList: {
      type: Array,
      default: () => [{}, {}],
    },
  },
};
  • 在组合式setup函数中,props也需要选项式定义,并且在setup的第一个参数接收
  • <script setup>中,defineProps不需要手动引入,且不能重复调用
// 如果仅在模板中使用props,可以不用接收defineProps的返回值
defineProps({
  pageType: {
    type: String,
    default: "task",
  },
  taskList: {
    type: Array,
    default: () => [{}, {}],
  },
});
// 如果需要在js中使用props,则接收defineProps的返回值
const props = defineProps(["pageType"]);
console.log(props.pageType)

1.3 computed方法

import { reactive, computed } from "vue";
const person = reactive({firstName: '张', lastName: '三'})
person.fullname = computed(() => person.firstName + person.lastName);

1.4 watch

image.png
  • watch一个ref


    image.png
  • watch一个响应式对象(监听整个对象的话,无法拿到正确的oldValue)

import { reactive, watch } from "vue";
const pageInfo = reactive({
  pageIndex: { value: 0 },
  pageSize: 20,
});
watch(pageInfo, () => { // 深层监听,内部变化都会触发
  console.log("pageInfo发生变化", pageInfo);
});
  • 如果只需要监听对象的某一个属性,需要用一个返回该属性的 getter 函数
watch(
  () => pageInfo.pageIndex.value, 
  () => {
    console.log("pageInfo发生变化", pageInfo);
  }
);
  • watchEffect简写 ↓
import { watchEffect } from "vue";
watchEffect(() => {
  console.log("type变化", type.value, pageInfo.pageSize);
});
// 发现甚至没有传我要watch谁,vue会自动跟踪回调的响应式依赖(你用谁我就监视谁)
// 也就是type.value 和 pageInfo.pageSize变化时都会执行该回调
// watchEffect的immediate为true

有点像computed,初始执行一次,依赖值改变时再执行一次
computed注重返回值。watchEffect注释过程
  • watchEffect的好处
    对于有多个依赖项的侦听器来说,避免多次使用watch来侦听
    watchEffect() 将只跟踪回调中被使用到的属性,而不是像深度跟踪器一样递归跟踪所有的属性

1.5 自定义指令

  • options中需要声明directives选项
export default {
    directives: {
        focus: (el) => { el.focus(); }
    }
};
  • <script setup>中使用命名方式来确定一个自定义指令
const vFocus = (el) => { // 类型可以是函数也可以是对象,对象的话可以配置指令的各个钩子
  el.focus(); 
};
// 只看代码的话会觉得这怎么就是个自定义指令呢?
// Vue定义的:<script setup> 中
// 靠命名来判定它是一个自定义指令:1: 变量以 v 开头  2: 驼峰式命名

// 那么假如我不知道这个规则,刚好这样命名了一个变量,值为原始类型?
结果是:不会报错,不过也没有什么效果罢了
指令钩子
bind  -》 beforeMount 指令与元素成功绑定
inserted -》 mounted 指令所在元素插入页面时 
update -》updated  父节点和子节点更新后调用

指令定义为函数类型时,默认钩子是:
——在Vue3中:mounted 和 updated
——在vue2中是:bind 和 update

2. setup选项:

setup是一个函数,需要有一个返回值(<script setup>则不需要返回值)

  • 当返回值是一个对象,则对象属性都能用于模板中
  • 也可以返回一个渲染函数,则忽略模板中的内容

但不能是一个async函数。唯一可以使用 async setup() 的情况是,该组件是 Suspense 组件的后裔。

setup中不包含对组件实例的访问权,它的执行执行时机在beforeCreate之前。
在 <script setup> 中创建的变量不会作为属性添加到组件实例中,这使得它们无法从选项式 API 中访问。如果是setup函数的返回值,则会添加,选项式API中可访问

setup函数收到的2个参数

image.png

3. toRef和toRefs

将响应式对象的某个属性交给另一个变量去使用时,不想丢失响应式。

image.png
image.png
image.png

4. shallowReactive和shallowRef

只对对象的根级别属性做响应式

  • shallowReactive


    image.png
image.png
  • shallowRef


    image.png

5. toRaw

返回代理对象的原对象。代理对象和原对象的联系:

  1. 一个是在reactiveMap中保存了这种关联关系(类型是WeakMap,key是原对象,value是代理对象)
  2. 一种是在new Proxy时配置的getter函数内部,可以同时访问到原对象和代理对象的引用
  • readonly包装一个reactive生成的响应式对象,再对它进行toRaw,结果还是最初的原始对象。所以toRaw并不是简单读取这个响应式对象上的__v_raw的属性,而是要递归取最原始的那个对象
const src = { info: { name: "祖先" } };
const ret = reactive(src);
const locked = readonly(ret);

console.log(toRaw(locked) === src); // true  —— readonly包装的对象toRaw也是那个最初的src,而不是ret
console.log(toRaw(ret) === src); // true
image.png

6. markRaw

将一个新对象挂在响应式对象上时它也会变成响应式对象,如果你不想为这个内部的对象做响应式,可以使用markRaw

const a = reactive({
    age: 20,
    tool: markRaw(Tooltip),
});
使用 markRaw 的前提是:你这个对象(例如上面的Tooltip)是一个不会更改的对象,而且不应在模板中使用
因为 markRaw 虽然为你跳过了响应式,一旦你改了这个对象(Tooltip,而且模板中展示了这个Tooltip)
而当响应式对象中其他数据发生变更(例如改变age)导致模板更新,则这个对象的变更也会反映在模板上
  • markRaw和readonly的区别
    image.png

7. customRef

借用vue的【收集依赖track】和【通知更新trigger】,再加上自己的getter和setter拦截逻辑,创建一个自定义ref。

  • 如果不拦截set的赋值逻辑,只是在值修改的时候执行其他逻辑,那么watch也可以实现
  • 不过想要拦截getter的话,就可以用customRef,自已定义【一部分】getter和setter逻辑
  • customRef传入一个工厂函数,这个工厂函数接收2个参数:track, trigger,并返回一个有get和set方法的对象。
import { customRef } from "vue";

const debounceChangeValue = (value, interval) => {
  let timer = null;
  return customRef((track, trigger) => {
    // customRef传入一个工厂函数,这个工厂函数接收2个参数:track, trigger
    // 并返回一个有get和set方法的对象
    return {
      get() {
        track(); // 收集依赖(必需)
        return value;
      },
      set(newValue) {
        clearTimeout(timer);
        timer = setTimeout(() => {
          value = newValue;
          trigger(); // 数据修改之后需要通知依赖(必需)
        }, interval);
      },
    };
  });
};

const text = debounceChangeValue("初始值", 300);

8. provide/inject

<script setup>中,祖先已经可以向后代组件提供响应式数据了

  • 响应式数据的控制权应掌握在提供方手里(可以对外提供 【readonly的数据】和【修改函数】供后代调用,而修改权仍然在提供方)


    image.png

9. 一些判断函数: isRef / isReactive / isReadonly / isProxy

10. 内置组件:Teleport 传送

它可以将组件内部的一部分模板传送到该组件DOM之外的结构中去,即该组件内部的DOM不再受组件层级的影响。

<Teleport to="body">
      <p>我的DOM直接添加在body下面</p>
</Teleport>
<Teleport to="#app">
      <p>我的DOM直接追加在#app里面</p>
</Teleport>

11. 内置组件:Suspense 悬而不决

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容