vuejs知乎_Vue Composition Api 介绍

vuejs知乎_Vue Composition Api 介绍_第1张图片

Vue进入新的历史进程了,相信喜欢Vue的小伙伴都非常高兴。

下面来介绍 Vue Composition Api,你也可以粗暴地理解成 Vue3,可以在观望查看 Vue3 的相关介绍:

Vue Composition​composition-api.vuejs.org

那就先来过一遍吧:

reactive:

const someObj = reactive({
      a:xxx,b:xxx})

ref:

const someValue = ref(xxx)

官方解释了 ref 和 reactive 的区别:https://composition-api.vuejs.org/zh/#ref-vs-reactive,其实一个是用来指定变量的(ref 不一定只能是基本数据类型),一个是用来指定对象的。

为什么会出现这种区别呢?

用过 React 的朋友应该能理解,其实二者都是 useState,都是会导致视图响应式变更的“数据”,但是通常情况下,因为 React 的不变性要求,你需要如此处理响应式对象和普通数据:

// 声明
const [normalValue,setNormalValue] = useState('')
const [objValue,setObjValue] = useState({
      a:1,b:2})

// 变更
setNormalValue('new')
setObjValue(val=>({...val,a:2}))

可以看到,在 React 中,为了使用 Object 时保证不可变性,变更需要通过向 set 函数传入一个新对象办到。

守住不变性的原则固然重要,但是在实际开发中,却有有些不近人情的味道 —— 代码中无任何赋值语句 —— 违反直觉的写法不一定能得到所有人的认同

毕竟 JS 不是 Lisp,极客精神确实可以写出优秀代码,但是接地气也同样重要。

剩下的 api 其实都没啥好聊的。


逻辑复用

这个词其实有些误导,所谓的逻辑复用,其实指的就是与视图相关的很多逻辑,并不一定需要你写在视图当中了,你可以这样:

在任意一个文件中写组件相关的逻辑:

function useLogic(){
      
  const el = ref(null)
  const data = reactive({
      name:''})
  onMounted(()=>{
      
    data.name = 'shown'
    el.value.style.backgroundColor = 'red'
  })
  return {
      
    el,
    data
  }
}

在组件中,引入逻辑:

export default {
      
  name:'some component',
  setup(){
      
    const {
       data, el } = useLogic()
    return ()=> (
{ data.name}
) } }

这样就可以保持组件的精简了。

同时,配合 “依赖注入”,可以达到跨组件的响应式数据传递。

// 复用逻辑文件中加入token 声明
export const logicToken = Symbol()

// 父组件
setup(){
      
  const logic = useLogic()
  provide(logicToken,logic)
  return ()=> (
) } // 孙组件 setup(){ const logic = inject(logicToken) return ()=>(
) }

这样就能够在孙组件中使用 “单例的跨组件逻辑”了。

可以说除了调试和时间旅行支持以外,vuex 的所有功能被全包。

function useLikeVuex(){
      
  // state
  const state = reactive({
      name:''})
  // mutation
  function testMutation(val){
      
    state.name = val
  }
  // action
  async function testAction(val){
      
    await someAsyncFunction()
    testMutation(val)
  }
  return {
      state,testMutation,testAction}
}

唯一不同之处在于,你可以在任意一个组件中,注入这个 类 vuex 的结构。

当然,没有强制的规则,需要更多地靠自己解决。

在这里推荐一个 babel 插件,可以跳过书写 {name:xxx, setup(){}} 的过程,直接 “函数即组件”。

babel-preset-vca-jsx​www.npmjs.com
vuejs知乎_Vue Composition Api 介绍_第2张图片

效果如下:

vuejs知乎_Vue Composition Api 介绍_第3张图片

之后的文章也将采用这种写法,当然,这样的写法目前还有些亟待解决的问题,比如自定义组合函数导出 ref 无法绑定之类的,但是可以通过本地声明用 watchEffect 手动绑定。


新的思考

React Hooks,Vue Composition,Angular rxjs+service,我们可以统称他们为:

响应式逻辑复用

它由两部分组成:

  1. 实现响应式,并且与视图分离
  2. 依赖注入(或者叫上下文注入)

简要介绍一下三大框架是如何在 api 层面解决这个问题的:

React:useState,useReducer (memorized state)实现响应式,useContext/createContext 实现依赖注入

Vue: ref, reactive (proxy)实现响应式,provide/inject 实现依赖注入

Angular: rxjs (zone)实现响应式,service/module 实现依赖注入(并且实现了依赖查找和自动初始化,只需要声明 provider,即可直接操作实例化对象)。

现有前端主流框架几乎都已经很方便地支持这样的特性,那这样会带来什么样的变化呢?

何时使用props

组件参数何时才需要用呢?

通常我们会认为,需要向子组件传递数据的时候使用,然而现在,你为何不将子组件,孙组件,父组件的逻辑提取出来在一处处理呢?

const logicToken = Symbol()
// 父子组件的逻辑都在此处处理
function logic(){
      
  return {
      
    showModal: ref(false)
  }
}

// 父组件声明
function Parent(){
      
  const logicService = logic()
  provide(logicToken,logicService)
  return ()=>(
) // 你并不需要传入 props } // 子组件注入 function Child(){ const logicService = inject(logicToken) const { showModal} = logicService return ()=> () }

这里你会发现,完全用不到 props,你也不需要去纠结 prop 的各种问题,类似 初始化,校验之类的。

那是不是就用不到 props 了呢?不是的,你可以这么理解,凡是需要迭代数据的地方,都是需要 props 的:

()=> (
{ list.map(el=>) }
)

明白了吧,props 的存在,其实也是由于对象的可变性导致了,因为统一处理对象的时候,对象层次深,响应式负担重,处理麻烦,所以才需要有 props 来简化这个过程,换句话说:

让数据结构匹配组件结构

延展出来,你就会发现 vue composition 处理逻辑比 vuex 优秀的地方 ——

你可以通过 props 声明一个新的 逻辑依赖:

// 这是一个依赖于 props 的自定义组合函数
function logic(props){
  const data = reactive({name:''})
  watch(props,(val,preVal)=>{
    data.name = props.value
  })
  return data
}

// 组件
function SomeCompoennt(props){
  const data = logic(props)
  return ()=>(
) }

明白了吧,这也是 vue composition api 比 当前版本 vuex 优秀的最重要一点。

你可以将逻辑和状态,依托组件props,组成一个树型结构!

每一个自成一体的“小vuex”里,你可以只处理自己用得到的逻辑,最后将其通过props/watch等api,与顶层或者底层的 “小vuex”联系起来就可以了。

如果你的 “小vuex”,也就是自定义组合函数,是按照业务逻辑划分的,那我们就可以理直气壮地将这种:

面向业务划分模块,彼此通过信息传递相互作用

的方式,叫做一个字:

是的,这就是微前端,或者说业务模块化。


微的威力

可能很多人不了解 vue composition 可能带来的变化,这和微服务可能在后端带来的变化是异曲同工的,可以参考 React 平台的各种第三方hook:https://ahooks.js.org/zh-CN,https://github.com/vercel/swr,以及 Angular 平台的各种 Module,https://material.angular.cn/cdk/categories

大家现在需要自己去实现的 表单表格联动,复杂请求,拖拽组件 等逻辑,届时可能就只是放两三个参数,填几个空的问题了。

vue 生态也会从 “帮你做视图”转换成 “帮你写逻辑”,类似 $refs.form.validate 这样的丑陋代码,将成为历史。

所以大家不需要惊慌,vue 的 api 面积将大大缩小,新的 vue 比 上一个版本不一定会更容易学。

但一定更容易用!

你可能感兴趣的:(vuejs知乎)