今天看啥  ›  专栏  ›  丰言丰语

随手记Vue3.0文档阅读差异(2)

丰言丰语  · 掘金  ·  · 2021-05-20 20:58

文章预览

阅读 57

随手记Vue3.0文档阅读差异(2)

引言

本文为作者记录自身所理解的2.*与3.0差异,主要是帮助作者自身理解3.0,并非严谨的教学,如出现不准确的地方,请勿责怪,相互学习(废话还是再说了一次),如果大家对上一篇感兴趣👏点击这里查看,这一篇的主要内容是讲的作者对于composition api在使用上的一些想法,不喜勿喷,互相学习。

组合式API

来到正题,首先我希望你对Vue2.*有着比较深入的理解不然,可能其实接下来的内容并不是你特别需要关注的一些内容点,你可能先做的一件事情就是先去学习2.*的语法以及使用方式

option api

首先我们先来回顾一下option api的配置方式或者方法

// some.vue
<template>
    <!-- some dom -->
</template>
<script>
export default {
    data () {
        return {
            someData: 'someDataDefine'
        }
    },
    methods: {
        someFuntion () {
            // do something
        }
    }
}
</script>
复制代码

以上内容是我们在一个单文件组件中基本都可以看到的写法,这种写法有什么好处在于哪里呢?作者认为(仅仅是作者认为)当一个组件它是简单业务组件或者是纯UI组件的时候,这种聚合的写法是很好的,可以很清晰的看出来我在一个组件内所有配置项,组件内的状态/方法/props都是非常直观的。但是我们换一个场景,比如以下这个场景

思考?

// some.vue
<template>
    <div>
        {{dataA}}
        {{dataB}}
        <button @click="fundctionA">改变A</button>
        <button @click="fundctionB">改变B</button>
    </div>
</template>
<script>
export default {
    data () {
        return {
            dataA: 'a',
            dataB: 'b'
        }
    },
    methods: {
        fundctionA () {
            this.dataA = 'new a'
        },
         fundctionB () {
            this.dataB = 'delete b'
        }
    }
}
</script>
复制代码

这个是一个非常常见的场景了吧,然后这个时候我们要增一个C我们应该怎么做呢?首先我要增加一个{{dataC}}并且在data里面增加对应dataC的定义,接着我要在增加fundctionC,然后再相应的增加一个<button>标签去绑定对应点击事件,是不是相对来说是比较麻烦的。

这里给大家思考两分钟我们应该如何去抽象封装呢?

抽离与耦合

其实作者认为这里有两种思维模式

方式一

这种思维是我们把所需要的DOM跟业务逻辑组合在一起,比如说下方组件A

// comA.vue
<template>
    <div>
        {{dataA}}
    </div>
</template>
<script>
export default {
    data () {
        return {
            dataA: 'a',
        }
    },
    methods: {
        fundctionA () {
            this.dataA = 'new a'
        }
    }
}
</script>
复制代码

这里的话我们就相当于将(状态/视图/方法)都绑定在一个单元内,这种做法的好处在与组件外部不太需要关心内部视图与状态的管理,只需要按照暴漏的内容进行使用即可。这种适用视图场景与数据状态组合都比较固定的场景,比如常见的UI组件弹窗,消息等,是比较适合使用这种方式做的。

方式二

回到一个Vue组件,实际上我们可以认为它是有做两个部分的组成(视图层/逻辑层),我们可能会出现一个场景是在于我们的业务数据/业务场景/数据流/业务模式可能是固定。而使用我们相关数据去做的渲染的UI是不确定的,这个时候我们预期去做一个业务的最小单元的时候,如果在我们原来2.*的版本中我们可以怎么做,大概率会有几个不同的做法做法,但是其实可能会比较类似,举个我司的案例,我司主要以金融服务为主,那么可能经常遇到的场景就是需要去整合金融产品信息,那么这个时候可能会有一个相关的产品列表的单元需要我们去做处理,我可能会这么去做

创建一个fund.service.js

class Fund {
    constructor () {
        this.list = []
    }
    // 获取列表信息
    async getList () {
        if (this.list.length === 0) {
            this.list = await api.getList()
        }
        return this.list
    }
    // 查找相关产品
    findItem (code) {
        return this.list.find(item => item.code === code)
    }
}
export default new Fund()
复制代码

在对应的页面组件上page.vue

<template>
    不确定部分
</template>
<script>
import fund from './fund.service.js'
export default {
    data () {
        return {
            list: []
        }
    },
    created () {
        this.getData()
    },
    methods: {
        async getData () {
            this.list = await fund.getList()
        },
        findItem: (...params) => fund.findItem(...params)
    }
}
</script>
复制代码

2.*的写法可能就是类似这样子,这里面其实存在几个问题,首先我们抽离出来放在class里面的逻辑/方法/数据从单元中取出来的时候还是需要对他们进行类型分割,当然我们也可以通过一些对应的预处理方法来解决这类问题,但是只要是经过预处理或者改造的总归是不够直观并且存在一定的上手成本。接着我们尝试使用composition api来对上面的案例进行分解

创建一个useFund.js

import { reactive, Ref } from 'vue'
export const useFund = () => {
    const fundlist = reactive([])
    async getList () {
        const list = await api.getList()
        list.forEach(item => {
            fundlist.push(item)
        })
    }
    findItem (code) {
        return this.list.find(item => item.code === code)
    }
    return {
        getList,
        findItem,
        fundlist
    }
}
复制代码

在对应的页面组件上page.vue

<template>
    不确定部分
</template>
<script>
import { useFund } from './useFund.js'
export default {
    setup () {
        return {
            ...useFund()
        }
    }
}
</script>
复制代码

我们会发现composition api的写法在页面上会简洁很多,这样有利于我们把页面的关注度放在数据交互上,而不是业务编写上。有利于做业务做封装,做单元化

到此为止我的胡说八道结束,感谢大家观看~~

………………………………

原文地址:访问原文地址
快照地址: 访问文章快照
总结与预览地址:访问总结与预览