vue-next 函数式 api

时间: 2019-09-24阅读: 464标签: api

写在前面

在分享 vue-next 各个子模块的实现之前,我觉的有必要比较全面的整理下 vue-next 中提出的函数式 api,了解这些的话,无论是对于源码的阅读,还是当正式版发布时开始学习,应该都会有起到一定的辅助作用。

类似的东西在网上有很多,只是会比较零碎,同时有些也相对过时了,当然当前整理的这些也有可能会过时,毕竟代码还处于 pre-alpha 的阶段,但其中的设计思想应该是不会改变了。


setup

setup 会作为编写组件业务逻辑的主战场,各种 hook 类型的方法均需要在 setup 这个作用域下调用,直接来看 RFC 中的例子:

<template>
  <button @click="increment">
    Count is: {{ state.count }}, double is: {{ state.double }}
  </button>
</template>

<script>
import { reactive, computed } from 'vue'

export default {
  setup() {
    const state = reactive({
      count: 0,
      double: computed(() => state.count \* 2)
    })

    function increment() {
      state.count++
    }

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

其代码结构看起来和 vue2 基本保持一致,不过有以下几点需要注意:

  • setup 本身的调用时机,从目前的源码来看,介于 beforeCreate 和 created 这两个生命周期之间,言外之意,就是你无法在这里使用 this 指向当前组件实例
  • 对于 state 的声明,我们使用 reactive 这个 api 来构造,对于 computed state 的声明,使用 computed,两者本质上均是 Proxy 对象
  • 对于组件方法的声明,我们直接通过声明普通函数的方式进行声明即可,对于 state 的变更,直接通过闭包使用 reactive 返回的 Proxy 对象即可
  • setup 的返回值被称作 render context,顾名思义,就是模板中可以访问到的各种数据和方法的上下文对象,我在之前的文章中曾提及,模板在解析数据时,会优先考虑从 data 对象取值,之后就是这个 render context 了
  • 除了返回 render context,还可以返回模板渲染函数,对,就是那个 h(...),这种形式对应的情况是,当我们没有声明 template 属性时

在 vue-next 中,我们直接从 vue 导入 reactive 、computed 以及其他的 api 即可,如果在 vue2 版本上,我们还可以通过使用 composition-api 这个 plugin 来使用这些 api。


state 

声明 state 主要有以下几种形式。


基础类型

基础类型可以通过 ref 这个 api 来声明,如下:


import { ref } from "vue";

export default {
setup() {
  const count = ref(0);
  
  function inc() {
    count.value++;
  }
  
  return { count, inc };
}
};

之所以要通过 ref,是因为 js 中的基础类型传值不是引用传值,因此 vue-next 内部会自动将它封装为一个 ref 对象,其值指向原始值。当然,ref 指向引用类型也是没有问题的,其 value 指向引用类型变量的引用。


引用类型

引用类型除了可以使用 ref 来声明,也可以直接使用 reactive,如下:

import { reactive } from "vue";

export default {
  setup() {
    const state = reactive({
        count: 0
    });
    
    function inc() {
      state.count++;
    }
    
    return { state, inc };
    // 或者通过 toRefs 方法
    // return { ...toRefs(state), inc };
  }
};

这里使用 toRefs 的原因主要是因为,如果是 reactive 产生的对象,由于我们要只是保存对于该 Proxy 对象的引用,我们无法使用解构来将它 flat,而 toRefs 会将每一个属性在内部包裹为一个 ref 对象。


props

对于 prop 可以通过如下代码声明及使用:

export default {
  props: {
    count: Number
  },
  setup(props) {
    watch(() => {
      console.log(\`count is: \` + props.count)
    })
  }
}

这里可以发现其实和 vue2 中声明的方式基本一样,但值得注意的是,在 vue-next 中,props 的类型声明不是必须的,如果你使用 typescript,完全可以改写为如下的版本:

interface PropTypesI {
   count: number
}

export default {
  setup(props: PropTypesI) {
    watch(() => {
      console.log(\`count is: \` + props.count)
    })
  }
}

除此之外,还可以直接通过 watch 方法来观察某个 prop 的变动,这是为什么呢?答案非常简单,就是 props 本身在源码中,也是一个被 reactive 包裹后的对象,因此它具有响应性,所以在 watch 方法中的回调函数会自动收集依赖,之后当 count 变动时,会自动调用这些回调逻辑。


context

在 setup 那一小节中,我们知道,setup 在调用时,组件实例还未创建,那意味着我们无法使用 this 访问当前实例,那我想通过 this 在 vue2 中访问一些内置属性,怎么办?比如 attrs 或者 emit。我们可以通过 setup 的第二个参数:

setup(props, context) {
  do anything...
}

这个 context 对象也是一个 Proxy 对象,当我们通过 context.attrs 访问其属性时,本质上代理对象会将访问指向组件的内部实例(即之间文章中提及的 componentInternalInstance)。


生命周期

每一个 vue2 中的组件生命周期函数,当前都对应一个生命周期 hook,比如:

import { onMounted, onUpdated, onUnmounted } from "vue";

setup() {
  onMounted(() => { ... });
  onUpdated(() => { ... });
  onUnmounted(() => { ... });
}

这里值得注意的一点在于,对于 beforeCreate 和 created 生命周期,虽然有响应的 hook,但是我觉的没有必要单独使用了,因为这些逻辑代码大部分是一些初始化逻辑的代码,直接写在 setup 方法中即可。


如何复用代码

在这个基础上,复用代码的方式也不再像 vue2 中的那样,通过 mixin 或者 HOC 来达到复用代码的目的,这里稍微说一下,这些复用代码方式中比较显著的缺点有:

  • 隐藏了数据来源,主要体现在 mixin 中
  • 会牺牲一些性能,主要体现在 HOC 中
  • 可能会遇到命名冲突问题,主要体现在 mixin 中

在 vue-next 中,复用代码的逻辑本质上是利用这些 hook 来拆分业务逻辑与状态,如果你比较熟悉 react hooks 的话,应该很快就能明白我指的是什么意思。如果我们将逻辑都写在 setup 方法中,很快代码就会变得难以维护,在这方面,我们可以将一些耦合在一起的代码抽离出来,同时以 use 前缀命名,声明一个自定义的 hook,如下:

export default {
  setup() {
    const data = useSearch()
    const { sortedData, sort } = useSorting(data)
    return { data, sortedData, sort }
  }
}

function useSearch() { 
    ...fetch data
}

function useSort(data) { 
    ...sort data
}

除了以 inline 的方式来声明,还可以将这些自定义的 hook 声明在单独的文件中,直接通过 import 导入即可,比如:

import useSearch from '@hooks/search'
import useSort from '@hooks/sort'


与 react hooks 对比

vue-next 在这方面借鉴了 react hooks 的设计思想,但是从实现层来讲,它们是不一样的,主要有以下几点:

  • vue-next 不依赖于其调用顺序,而 react 依赖
  • vue-next 提供了生命周期方法,而 react 刻意模糊生命周期的概念
  • vue-next 基于响应式系统实现,意味它的依赖不需要显示声明(而且是自动的),而 react 需要手动声明依赖数组

公众号:全栈_101  


吐血推荐

1.站长广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入...

2.休闲娱乐: 直播/交友    优惠券领取   网页游戏   H5游戏

链接: http://www.fly63.com/article/detial/6118

超赞的腾讯短网址(微信url.cn短链接)生成api接口

腾讯短网址的应用场景很广,譬如短信营销、邮件推广、微信营销、QQ营销、自媒体推广、渠道推广等,都会用到短网址。究其原因是在于短网址可以降低推广成本、用户记忆成本,提高用户点击率;在特定的场景下推广还能规避关键词,防止域名被拦截

JSON Web 令牌(JWT)是如何保护 API 的?

你可以已经听说过 JSON Web Token (JWT) 是目前用于保护 API 的最新技术。与大多数安全主题一样,如果你打算使用它,那很有必要去了解它的工作原理(一定程度上)。问题在于,对 JWT 的大多数解释都是技术性的,这一点让人很头疼。

HTML5常用API

该API可以用来检测页面对于用户的可见性,即返回用户当前浏览的页面或标签tap的状态变化。 在最小化浏览器、切换tap页面时生效.(如需对app中几个webview进行切换操作时

API接口设计,需要注意这4点

原则上API接口设计一般出现在开发的详细设计中,但是随着诸多公司建立开放平台,产品经理也逐渐需要能理解API接口,尤其是做平台性的产品,还要学会定义接口。本文就关于产品经理在设计接口中需要定义什么

vue之按钮权限及优雅请求API

系统开发中按钮级权限控制也是非常重要的功能之一,可以严格控制不同角色用户所拥有的功能权限。首先可以通过vue的自定义指令来控制按钮(div,link也阔以)等的显示与否以及是否禁用状态。

webService和Restful

restful是一种架构风格,其核心是面向资源,更简单;而webService底层SOAP协议,主要核心是面向活动;两个都是通过web请求调用接口

使用 JS 来动态操作 css ,你知道几种方法?

JavaScript 可以说是交互之王,它作为脚本语言加上许多 Web Api 进一步扩展了它的特性集,更加丰富界面交互的可操作性。这类 API 的例子包括WebGL API、Canvas API、DOM API,还有一组不太为人所知的 CSS API

在 Node.js 上运行 Flutter Web 应用和 API

大量的跨平台应用开发框架,使你可以编写一次代码,然后在 Android,iOS 等多个平台上甚至在台式机上运行。你可能听说过一些流行的框架,例如 Ionic,Xamarin 和 React Native。另一个相对较新的框架是 Flutter

解锁设计优质API的五种秘籍

如今,随着我们构建软件方式的变化,以及API平台的爆炸式激增,各大公司都必须以更快的速度构建出自己的产品、并推向市场。目前,几乎所有的软件需求都需要通过API来提供相应的解决方案,其中包括:支付类API、通信类API

Moment.js常用API速查

日常开发经常会用Moment.js来处理时间,现对频繁使用的几个API做下整理,以便日后查阅。

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

文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全