让Vue3 Composition API 存在于你 Vue 以外的项目中

更新日期: 2020-12-16阅读: 1.5k标签: API

作为新特性 Composition api ,在 vue3 正式发布之前一段时间就发布过了。

距文档介绍, Composition API 是一组低侵入式的、函数式的 API,使得我们能够更灵活地「组合」组件的逻辑。

不仅在 Vue 中,在其他的框架或原生 JS 也可以很好地被使用,下面我们就选取几个比较重要的 Composition API ,通过一些简单的例子来看看如何在其他项目中使用。

注:本文仅列出各个分类下比较重要的 API,想要查看全部可以点击下方链接进行查看:https://github.com/vuejs/


reactive API

createReactiveObject

createReactiveObject 函数是 reactive API 的核心,用于创建 reactive 对象 。

在分享 API 之前,我们先看看其核心实现,由于篇幅有限,本文仅展示出理解后的简化版代码,代码如下:

function createReactiveObject(
  target, // 要监听目标
  isReadonly, // 是否只读
  baseHandlers, // target 为 Object 或 Array 时的处理器,支持对数据的增删改查
  collectionHandlers // target 为 Map/WeakMap 或 Set/WeakSet 时的处理器,支持对数据的增删改查
) {
    if (target[ReactiveFlags.RAW] && !(isReadonly && target[ReactiveFlags.IS_REACTIVE]) {
      // 当 target 已经是一个 Proxy 时,直接返回
      // 例外情况:在 Proxy 里调用 readonly()
        return target
    }
    // 当前对象已被监听过时,就直接返回被监听的对象
    if (existingProxy) {
      return existingProxy
    }
    // 如果是 Object Array Map/WeakMap Set/WeakSet 以外只能监听到值的数据,直接返回
    if (targetType === TargetType.INVALID) {
      return target
    }
    // 根据参数类型生成对应的 Proxy 对象,以及添加对应的处理器
    const proxy = new Proxy(
      target,
      targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
    )
    proxyMap.set(target, proxy)
    return proxy
}

reactive

接收一个普通对象然后返回该普通对象的响应式代理。等同于 2.x 的 Vue.observable()

示例如下:

import {
  reactive,
  isReactive // 判断是否是 reactive 对象
} from 'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'
const obj = {
  nested: {
    foo: 1
  },
  array: [{ bar: 2 }]
}
const value = 10

const observedObj = reactive(obj)
const observedValue = reactive(value)

console.log(isReactive(observedObj)) // true
console.log(isReactive(observedValue)) // true

shallowReactive

只为某个对象的私有(第一层)属性创建浅层的响应式代理,不会对“属性的属性”做深层次、递归地响应式代理,而只是保留原样。

示例如下:

const obj = {
  nested: {
    foo: 1
  },
  array: [{ bar: 2 }]
}
const value = 10

const unobservedObj = shallowReactive(obj)
const unobservedValue = shallowReactive(value)

console.log(isReactive(observedObj)) // false
console.log(isReactive(observedValue)) // false


effect API

createReactiveEffect

createReactiveEffect 是 effect API 的核心,用于创建监听用户自定义的 reactive 对象的函数

在分享 API 之前,我们先看看其核心实现,由于篇幅有限,本文仅展示出理解后的简化版代码,代码如下:

function createReactiveEffect(
    fn, // 用户创建的 reactive 对象变动执行回调
  options = {
    lazy, // 是否执行用户函数
    scheduler, // 收集数据记录
    onTrack, // 追踪用户数据的回调
    onTrigger, // 追踪变更记录
    onStop, // 停止执行
    allowRecurse // 是否允许递归
  }
) {
    const effect = function reactiveEffect() {
      if (!effectStack.includes(effect)) {
        cleanup(effect) // 清空 effect
        try {
          enableTracking() // 往追踪用户数据的栈内添加当前 effect
          effectStack.push(effect) // 往 effect 栈内添加 effect
          activeEffect = effect // 将活动 effect 变成当前 effect
          return fn() // 执行回调
        } finally { // 删除当前记录
          effectStack.pop()
          resetTracking()
          activeEffect = effectStack[effectStack.length - 1]
        }
      }
    }
        effect.id = uid++
    effect._isEffect = true
    effect.active = true
    effect.raw = fn
    effect.deps = []
    effect.options = options
    return effect
}

effect

effect 函数是 effect API 的核心。以 WeakMap 为数据类型,是一个用于存储用户自定义函数的 订阅者

示例如下:

let dummy
const counter = reactive({ num: 0 })
effect(() => (dummy = counter.num))
console.log(dummy === 0) // true
counter.num = 7
console.log(dummy === 7) // true


ref API

RefImpl

RefImpl 是 ref API 的核心,用于创建 ref 对象

在分享 API 之前,我们先看看其核心实现,代码如下:

class RefImpl {
  private _value // 存储当前 ref 对象的值

  public __v_isRef = true // 确定是否为 ref 对象的变量 (只读)

  constructor(
    private _rawValue, // 用户传入的原始值
    public readonly _shallow = false // 当前 ref 对象是否为 shallowRef
  ) {
    // convert:如果传入的原始值为对象,则会被 convert 函数转换为 reactive 对象
    this._value = _shallow ? _rawValue : convert(_rawValue)
  }

  get value() {
    // 用于追踪用户输入的值变化
    // track:effect api 的 track 函数,用于追踪用户行为,当前则是追踪用户的 get 操作
    // toRaw:effect api 的 toRaw 函数,将 this 转化为用户输入值
    track(toRaw(this), TrackOpTypes.GET, 'value')
    return this._value
  }

  set value(newVal) {
    if (hasChanged(toRaw(newVal), this._rawValue)) {
      // 当前 ref 对象有变化时
      // _rawValue / _value 变更
      // trigger:effect api 的 trigger 函数,根据用户传入的值与操作类型来进行操作,当前则为将用户传入的值添加到值 map 里
      this._rawValue = newVal
      this._value = this._shallow ? newVal : convert(newVal)
      trigger(toRaw(this), TriggerOpTypes.SET, 'value', newVal)
    }
  }
}

ref

接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性 .value。如果传入 ref 的是一个对象,将调用 reactive 方法进行深层响应转换。

示例如下:

const count = ref({
  name: '鱼头',
  type: '帅哥'
})
console.log(count.value.type) // 帅哥
count.value.type = '超级大帅哥'
console.log(count.value.type) // 超级大帅哥

shallowRef

创建一个 ref ,将会追踪它的 .value 更改操作,但是并不会对变更后的 .value 做响应式代理转换(即变更不会调用 reactive)

示例如下:

const __shallowRef = shallowRef({ a: 1 })
let dummy
effect(() => {
  dummy = __shallowRef.value.a
})
console.log(dummy) // 1

__shallowRef.value.a = 2
console.log(dummy) // 1
console.log(isReactive(__shallowRef.value)) // false

customRef

customRef 用于自定义一个 ref,可以显式地控制依赖追踪和触发响应,接受一个工厂函数,两个参数分别是用于追踪的 track 与用于触发响应的 trigger,并返回一个带有 get 和 set 属性的对象。

示例如下:

let value = 1
let _trigger

const custom = customRef((track, trigger) => ({
  get() {
    track()
    return value
  },
  set(newValue) {
    value = newValue
    _trigger = trigger
  }
}))

let dummy
effect(() => {
  dummy = custom.value
})
console.log(dummy) // 1

custom.value = 2
console.log(dummy) // 1

_trigger()
console.log(dummy) // 2

triggerRef

triggerRef 用于主动触发 shallowRef

示例如下:

const __shallowRef = shallowRef({ a: 1 })
let dummy
effect(() => {
  dummy = __shallowRef.value.a
})
console.log(dummy) // 1

__shallowRef.value.a = 2
console.log(dummy) // 1
console.log(isReactive(__shallowRef.value)) // false

triggerRef(__shallowRef)
console.log(dummy) // 2


computed API

ComputedRefImpl

ComputedRefImpl 是 ref API 的核心,用于创建 computed 对象

在分享 API 之前,我们先看看其核心实现,由于篇幅有限,本文仅展示出理解后的简化版代码,代码如下:

class ComputedRefImpl {
  private _value // 当前值
  private _dirty = true // 当前值是否发生过变更

  public effect // effect 对象

  public __v_isRef = true; // 指定为 ref 对象
  public [ReactiveFlags.IS_READONLY]: boolean // 是否只读

  constructor(
    getter, // getter
    private _setter, // setter
    isReadonly // 是否只读
  ) {
    this.effect = effect(getter, {
      lazy: true,
      scheduler: () => {
        if (!this._dirty) {
          // 将变更状态变为 true
          // trigger:effect api 的 trigger 函数,根据用户传入的值与操作类型来进行操作,当前则为将用户传入的值添加到值 map 里
          this._dirty = true
          trigger(toRaw(this), TriggerOpTypes.SET, 'value')
        }
      }
    })

    this[ReactiveFlags.IS_READONLY] = isReadonly
  }

  get value() {
    if (this._dirty) {
      // 返回当前值
      // 将变更状态变为 false
      this._value = this.effect()
      this._dirty = false
    }
       // track:effect api 的 track 函数,用于追踪用户行为,当前则是追踪用户的 get 操作
    track(toRaw(this), TrackOpTypes.GET, 'value')
    return this._value
  }

  set value(newValue) {
    this._setter(newValue)
  }
}

computed

传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象。或者传入一个拥有 get 和 set 函数的对象,创建一个可手动修改的计算状态。

示例如下:

const count1 = ref(1)
const plus1 = computed(() => count1.value + 1)
console.log(plus1.value) // 2
plus1.value++ // Write operation failed: computed value is readonly

const count2 = ref(1)
const plus2 = computed({
  get: () => count2.value + 1,
  set: val => {
    count2.value = val - 1
  }
})
console.log(plus2.value) // 2
plus2.value = 0
console.log(plus2.value) // 0

链接: https://fly63.com/article/detial/9941

浏览器中的图像识别 API

在 Native 开发中,Android 和 IOS 平台都在系统层面直接提供给了应用开发识别图像的一些能力,比如对于二维码/条形码的识别,Android 可以使用 barcode API 、 iOS 可以使用 CIQRCodeFeature API 。

JavaScript的API设计原则

Js的API设计原则总共包含了七个大块。系卤煮自己总结的一些经验和教训。本篇博文同时也参考了其他一些文章,相关地址会在后面贴出来。很难做到详尽充实,如果有好的建议或者不对的地方,还望不吝赐教斧正。

适合写api接口文档的管理工具有哪些?

现在越来越流行前后端分离开发,使用ajax交互。所以api接口文档就变的十分有意义了,目前市场有哪些比较优秀的接口文档管理工具呢?比如:MinDoc,eoLinker,apizza,RAML,Swagger等等

前后端分离,如何防止api接口被恶意调用或攻击

无论网站,还是App目前基本都是基于api接口模式的开发,那么api的安全就尤为重要了。目前攻击最常见的就是“短信轰炸机”,由于短信接口验证是App,网站检验用户手机号最真实的途径,使用短信验证码在提供便利的同时,也成了呗恶意攻击的对象,那么如何才能防止被恶意调用呢?

JSON API免费接口_ 免费的天气预报、地图、IP、手机信息查询、翻译、新闻等api接口

整理提供最新的各种免费JSON接口,其中有部分需要用JSONP调用。方面前端同学的学习或在网站中的使用,包括:免费的天气预报、地图、IP、手机信息查询、翻译、新闻等api接口

什么是RESTful API?

要弄清楚什么是RESTful API,首先要弄清楚什么是REST。REST -- REpresentational State Transfer,英语的直译就是“表现层状态转移”。如果看这个概念,估计没几个人能明白是什么意思。

认识 Fetch API

Fetch API 已经作为现代浏览器中异步网络请求的标准方法,其使用 Promise 作为基本构造要素。Fetch 在主流浏览器中都有很好的支持,除了IE。

用一个通俗的例子讲清楚API

随着移动互联网的发展, 基于互联网的应用正变得越来越普及,在这个过程中,更多的平台将自身的资源开放给开发者来调用。对外提供的API 调用使得平台之间的内容关联性更强,同时这些开放的平台也为用户、开发者和中小网站带来了更大的价值。

docker提供api访问

环境centos,添加deamon.json后,dockerd命令可以启动docker,这时请求 127.0.0.1:2375 可以正常访问,使用systemctl无法启动docker的情况.无法启动docker:查看当前的docker配置

构建API的最佳编程语言是什么?

你是否正在设计第一个Web应用程序?也许你过去已经建立了一些,但是目前也正在寻找语言的变化以提高你的技能,或尝试新的东西。有了所有信息,就很难决定为下一个产品或项目选择哪种编程语言。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!