15 分钟掌握vue-next函数式api(小结)

写在前面

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

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

往期文章

15 分钟掌握 vue-next 响应式原理
vue-next/runtime-core 源码阅读指南

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 需要手动声明依赖数组

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vue2.0$nextTick监听数据渲染完成之后的回调函数方法

    vue里面本身带有两个回调函数: 一个是`Vue.nextTick(callback)`,当数据发生变化,更新后执行回调. 另一个是`Vue.$nextTick(callback)`,当dom发生变化,更新后执行的回调. 栗子: ... <ul id="demo"> <li v-for="item in list">{{item}}</div> </ul> ... new Vue({ el:'#demo', data:

  • Vue中之nextTick函数源码分析详解

    1. 什么是Vue.nextTick()? 官方文档解释如下: 在下次DOM更新循环结束之后执行的延迟回调.在修改数据之后立即使用这个方法,获取更新后的DOM. 2. 为什么要使用nextTick? <!DOCTYPE html> <html> <head> <title>演示Vue</title> <script src="https://tugenhua0707.github.io/vue/vue1/vue.js"&

  • 15分钟学会vue项目改造成SSR(小白教程)

    15分钟学会vue项目改造成SSR Ps:网上看了好多服务器渲染的例子,基本都是从0开始的,用Nuxt或者vue官网推荐的ssr方案(vue-server-renderer),但是我们在开发过程中基本上是已经有了现有的项目了,我们所要做的是对现有项目的SSR改造.那么这里,跟我一起对一个vue-cil2.0生成的项目进行SSR改造 关于这篇文章的案例源代码我放在我的github上面,有兴趣的同学,也可以去我的github查看我之前写的博客.博客 一.改造技术的分析对比. 一般来说,我们做seo有

  • 15 分钟掌握vue-next函数式api(小结)

    写在前面 在分享 vue-next 各个子模块的实现之前,我觉的有必要比较全面的整理下 vue-next 中提出的函数式 api,了解这些的话,无论是对于源码的阅读,还是当正式版发布时开始学习,应该都会有起到一定的辅助作用. 类似的东西在网上有很多,只是会比较零碎,同时有些也相对过时了,当然当前整理的这些也有可能会过时,毕竟代码还处于 pre-alpha 的阶段,但其中的设计思想应该是不会改变了. 往期文章 15 分钟掌握 vue-next 响应式原理 vue-next/runtime-core

  • 15分钟上手vue3.0(小结)

    Vue 3 还没有正式发布,但是 Alpha 版本已经发布了. 虽然官方还不推荐在生产环境中直接使用 Vue 3 ,但是提前学习总归是有好处的. 嘴上喊着老子学不动了,双手还是很诚实的打开了 Vue 3 文档 创建项目 Vue 官方很贴心的提供了一个 github 仓库,让我们能快速体验Vue 3的新特性: git clone https://github.com/vuejs/vue-next-webpack-preview.git vue3-start cd vue3-start npm in

  • 5分钟学会Vue动画效果(小结)

    本文介绍了5分钟学会Vue动画效果(小结),分享给大家,具体如下: 1.哪些元素/那些组件适合在那些条件下实现动画效果 条件渲染 (使用 v-if) 条件展示 (使用 v-show) 动态组件 组件根节点 简单经典例子:(文字隐藏到显示效果) <div> <button @click="show = !show">show toggle</button> <transition name="fade"> //fade

  • 如何使用 Rails 和七牛云存储,在 15 分钟内打造一个图片分享社交应用原型

    十年前,Web 应用框架 Rails 创始人 David Heinemeier Hansson 曾录制视频,向我们演示如何使用 Ruby on Rails 在 15 分钟内创作一个 blog 引擎.这个视频通过 Rails 优秀的 MVC .习惯优于配置(Convention over Configuration)等设计,以及强大的代码生成.scaffold 等功能,成功展示了 Ruby on Rails 编写 Web 应用核心功能的高效简洁.Ruby on Rails 这门技术也在 Web 2

  • Vue.js函数式组件的全面了解

    目录 前言 React 函数式组件 Vue(2.x) 中的函数式组件

  • vue项目proxyTable配置小结

    目录 前言 如何配置proxyTable 关于proxyTable的原理 前言 proxyTable是一个用于Vue.js应用程序的配置选项,它允许您在开发过程中代理后端API请求.这一功能的作用是解决由于浏览器的同源策略所限制而导致的跨域请求问题.当前端应用程序部署在一个Web服务器上并向不同的后端API发送请求时,这个功能就变得尤为重要. 在Vue.js应用程序中使用proxyTable的主要优点是能够简化配置,方便地进行本地开发和调试.在开发过程中,可以将所有的API请求都代理到本地的开发

  • 15分钟提醒一次,珍惜时间啊

    15分钟提醒一次,珍惜时间啊保存为.vbs 复制代码 代码如下: today=Date() years=DatePart("yyyy",today)-1981-1 Days=DatePart("y",today)+25 If DatePart("m",today)=12 Then  if DatePart("d",today)>=9 Then  MsgBox "ok"  Years=Years+1  

  • vue项目中api接口管理总结

    默认vue项目中已经使用vue-cli生成,安装axios,基于element-ui开发,axiosconfig目录和api目录是同级,主要记录配置的相关. 1. 在axiosconfig目录下的axiosConfig.js import Vue from 'vue' import axios from 'axios' import qs from 'qs' import { Message, Loading } from 'element-ui' // 响应时间 axios.defaults.

  • 详解Vue.js项目API、Router配置拆分实践

    前后端分离开发方式前端拥有更高的控制权 随着前端框架技术的飞速发展,Router这个概念也被迅速普及到前端项目中,在早期前后的没有分离的时期下,并没有明确的路由概念,前端页面跳转大多是通过后端进行请求转发的,比如在Spring MVC项目中,进行一个页面跳转如下(画红线部分): 前端需要一个超链接,链接的href=/manager,这样这个超链接被转发到scs/waitFollowed路径指定的页面. 前后的分离后,前端页面跳转的方式发生了变化,不再需要后端处理了,数据交换方式也改变了,由此前端

随机推荐