VUE3 Composition API

1. Composition API(常用部分)

文档:

https://vue3js.cn/docs/zh/

setup

  • 新的option, 所有的组合API函数都在此使用, 只在初始化时执行一次
  • 函数如果返回对象, 对象中的属性或方法, 模板中可以直接使用

ref

  • 作用: 定义一个数据的响应式
  • 语法: const xxx = ref(initValue):
    • 创建一个包含响应式数据的引用(reference)对象
    • js中操作数据: xxx.value
    • 模板中操作数据: 不需要.value
  • 一般用来定义一个基本类型的响应式数据
<template>
  <h2>{{count}}</h2>
  <hr>
  <button @click="update">更新</button>
</template>

<script>
import {
  ref
} from 'vue'
export default {

  /* 在Vue3中依然可以使用data和methods配置, 但建议使用其新语法实现 */
  // data () {
  //   return {
  //     count: 0
  //   }
  // },
  // methods: {
  //   update () {
  //     this.count++
  //   }
  // }

  /* 使用vue3的composition API */
  setup () {

    // 定义响应式数据 ref对象
    const count = ref(1)
    console.log(count)

    // 更新响应式数据的函数
    function update () {
      // alert('update')
      count.value = count.value + 1
    }

    return {
      count,
      update
    }
  }
}
</script>

3) reactive

  • 作用: 定义多个数据的响应式
  • const proxy = reactive(obj): 接收一个普通对象然后返回该普通对象的响应式代理器对象
  • 响应式转换是“深层的”:会影响对象内部所有嵌套的属性
  • 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据都是响应式的
<template>
  <h2>name: {{state.name}}</h2>
  <h2>age: {{state.age}}</h2>
  <h2>wife: {{state.wife}}</h2>
  <hr>
  <button @click="update">更新</button>
</template>

<script>
/* 
reactive: 
    作用: 定义多个数据的响应式
    const proxy = reactive(obj): 接收一个普通对象然后返回该普通对象的响应式代理器对象
    响应式转换是“深层的”:会影响对象内部所有嵌套的属性
    内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据都是响应式的
*/
import {
  reactive,
} from 'vue'
export default {
  setup () {
    /* 
    定义响应式数据对象
    */
    const state = reactive({
      name: 'tom',
      age: 25,
      wife: {
        name: 'marry',
        age: 22
      },
    })
    console.log(state, state.wife)

    const update = () => {
      state.name += '--'
      state.age += 1
      state.wife.name += '++'
      state.wife.age += 2
    }

    return {
      state,
      update,
    }
  }
}
</script>

shallowRef and shallowReactive

shallowReactive : 只处理了对象内最外层属性的响应式(也就是浅响应式)

shallowRef: 只处理了value的响应式, 不进行对象的reactive处理

什么时候用浅响应式呢?

一般情况下使用ref和reactive即可
如果有一个对象数据, 结构比较深, 但变化时只是外层属性变化 ===> shallowReactive
如果有一个对象数据, 后面会产生新的对象来替换 ===> shallowRef

<template>
  <div>
    <div>
      <p>{{ counter.name }}</p>
      <button @click="handleCounter">add</button>
    </div>
    <div>
      <p>{{ user.name }}</p>
      <p>{{ user.age }}</p>
      <p>{{ user.hobby }}</p>
      <p>{{ user.child.value }}</p>
      <button @click="updateUser">update</button>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, shallowReactive, shallowRef } from 'vue';

export default defineComponent({
  setup() {
    // const counter = shallowRef(0);
    const counter = shallowRef({
      name: 'wanglizhi'
    });
    const user = shallowReactive({
      name: 'wanglizhi',
      age: 18,
      child: {
        id: 1,
        value: '11',
      },
      hobby: ['唱歌', '跳舞'],
    });

    function handleCounter() {
      counter.value.name = 'Leo';
      console.log(counter)
    }

    function updateUser() {
      // user.name = 'Leo';
      // user.age = 20;
      user.hobby[0] = '吃饭';
      user.child.value = '222';
      console.log(user)
    }

    return {
      counter,
      user,
      handleCounter,
      updateUser,
    };
  },
});
</script>

<style></style>

readonly and shallowReadonly

readonly:
深度只读数据
获取一个对象 (响应式或纯对象) 或 ref 并返回原始代理的只读代理。
只读代理是深层的:访问的任何嵌套 property 也是只读的。
shallowReadonly
浅只读数据
创建一个代理,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换
应用场景:
在某些特定情况下, 我们可能不希望对数据进行更新的操作, 那就可以包装生成一个只读代理对象来读取数据, 而不能修改或删除

<template>
  <div>
    <div>
      <p>{{ JSON.stringify(state) }}</p>
      <button @click="update">update</button>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, readonly, shallowReadonly } from 'vue';

export default defineComponent({
  setup() {
    const state = shallowReadonly({
      name: 'wanglizhi',
      age: 18,
      child: {
        name: 'xiaowang',
        age: 10,
        child: {
          name: 'wang',
          age: 1
        }
      }
    })

    function update() {
      state.name = 'Leo';
      state.child.name = 'Leo1';
      state.child.child.name = 'Leo2';
      console.log(state)
    }
    return {
      state,
      update,
    };
  },
});
</script>

<style></style>

toRaw and markRaw

toRaw
返回由 reactive 或 readonly 方法转换成响应式代理的普通对象。
这是一个还原方法,可用于临时读取,访问不会被代理/跟踪,写入时也不会触发界面更新。
markRaw
标记一个对象,使其永远不会转换为代理。返回对象本身
应用场景:
有些值不应被设置为响应式的,例如复杂的第三方类实例或 Vue 组件对象。
当渲染具有不可变数据源的大列表时,跳过代理转换可以提高性能。

<template>
  <div>
    <h2>toRaw and markRow</h2>
    <div>
      <p>{{ JSON.stringify(state) }}</p>
      <button @click="update">update</button>
    </div>
    <hr>
  </div>
</template>

<script lang="ts">
import { defineComponent, toRaw, markRaw, reactive } from 'vue';

export default defineComponent({
  setup() {
    const obj = {
      name: 'wanglizhi',
      age: 18,
      child: {
        name: 'xiaowang',
        age: 10,
        child: {
          name: 'wang',
          age: 1,
        },
      },
    };
    const obj3 = markRaw(obj);
    const state = reactive(obj3);
    const obj2 = toRaw(state);

    function update() {
      state.name = 'Leo';
      state.child.name = 'Leo1';
      state.child.child.name = 'Leo2';
      console.log('obj', obj);
      console.log('state', state);
      console.log('obj2', obj2);
      console.log(obj === state)
         console.log(obj2 === obj2)
    }
    return {
      state,
      update,
    };
  },
});
</script>

<style></style>

toRef 、toRefs、 isRef and unref

toRef
为源响应式对象上的某个属性创建一个 ref对象, 二者内部操作的是同一个数据值, 更新时二者是同步的
区别ref: 拷贝了一份新的数据值单独操作, 更新时相互不影响
应用: 当要将 某个prop 的 ref 传递给复合函数时,toRef 很有用
toRefs
将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的ref
isRef
判断是否为ref
unref
如果参数为 ref,则返回内部值,否则返回参数本身。这是 val = isRef(val) ? val.value : val

<template>
  <div>
    <h2>toRef and toRefs</h2>
    <div>
      <p>{{ JSON.stringify(state) }}</p>
      <button @click="update">update</button>
    </div>
    <hr>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRef, toRefs, isRef, unref } from 'vue';

export default defineComponent({
  setup() {
    const obj = {
      name: 'wanglizhi',
      age: 18,
      child: {
        name: 'xiaowang',
        age: 10,
        child: {
          name: 'wang',
          age: 1,
        },
      },
    };
    const state = reactive(obj);
    const obj2 = toRef(state, 'name');
    const obj3 = toRefs(state)

    function update() {
      // state.name = 'Leo';
      // state.child.name = 'Leo1';
      // state.child.child.name = 'Leo2';
      // obj2.value = 'haha'
      obj3.name.value = 'hehe'
      console.log('obj', obj);
      console.log('state', state);
      console.log('obj2', obj2);
      console.log('obj3', obj3);
      console.log(isRef(state))
      // console.log(isRef(obj2))
      // console.log(isRef(obj3))
      // console.log(isRef(obj3.name))
      // console.log(unref(state))
      // console.log(unref(obj2))
    }
    return {
      state,
      update,
    };
  },
});
</script>

<style></style>

customRef

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

推荐阅读更多精彩内容