前端开发那些事儿

第 008 期 用 Composition API 重构 Mix

2021-04-07  本文已影响0人  前端GoGoGo7

在 Vue 中,Mixins 可以包含任意组件的选项。这使得用 Mixins 能很方便的抽象多个组件间的公共部分,但也会带来一些问题:

  1. 命名冲突导致的运行结果的不确定性。组件 和 引入的 Mixins,引入的多个 Mixins 之间,都会出现数据名,方法名的命名冲突。出现命名冲突时,同名的数据或方法会被覆盖,对应的业务也就出错了。
  2. 隐式依赖导致的高耦合。组件 和 引入的 Mixins 之间会出现互相依赖的情况,如果依赖的数据或方法重命名了,数据或方法就找不到了。

Composition API 可以很好的解决这些问题。组件可以用 Composition API 暴露出的可响应数据。组件和 Composition API 不能读取和修改各自内部的数据和方法。

解决方案

我们来看个 Demo。做一个管理后台的列表页。列表页支持筛选搜索,显示列表,列表分页的功能。

用 Mixins 实现

可以将需要的组件的引入;列表,搜索条件分页数据;以及数据的交互放到 Mixins。如下:

import SearchForm from '@/components/search-form.vue'
import SearchItem from '@/components/search-item.vue'
import TableGrid from '@/components/search-item.vue'

export default {
  components: {
    SearchForm, // 搜索条件表单组件
    SearchItem, // 搜索条件组件
    TableGrid //表格组件
  },
  data() {
    return {
      list: [/* 列表数据 */], 
      searchQuery: {/* 搜索条件 */}, 
      pager: {/* 分页 */}
    }
  },
  mounted () {
    this.fetchList();
  },
  watch: {
    searchQuery: {
      handler() {this.fetchList()},
      deep: true
    }
  }, 
  methods: {
    fetchList() {/* 获取列表 */},
  }
}

列表页这么写:

<template>
  <div>
    <!-- 搜索功能 -->
    <SearchForm @search="fetchList">
      <div>
        <SearchItem title="姓名">
          <input type="text" v-model="searchQuery.name">
        </SearchItem>
      </div>
    </SearchForm>
    <!-- 表格 -->
    <TableGrid :list="list" :pager="pager"/>
  </div>
</template>

<script>
import listMixins from './mixin'
export default {
  mixins: [listMixins],
}
</script>

用 Composition API 重构

我们用 Composition API 来重构上面的 Mixins。如下:

import { onMounted, reactive, watch, toRefs } from 'vue'
import SearchForm from '@/components/search-form.vue'
import SearchItem from '@/components/search-item.vue'
import TableGrid from '@/components/search-item.vue'

export default function useList() {
  const data = reactive({
    searchQuery: {},
    list: [],
    pager: {}
  })

  const fetchList = () => {/* 获取列表 */}

  onMounted(fetchList)

  watch(() => data.searchQuery, fetchList, { deep: true })

  return {
    ...toRefs(data),
    fetchList,
    components: {
      SearchForm,
      SearchItem,
      TableGrid
    }
  }
}

列表页这么写:

<template>
  <div>
    <!-- 搜索功能 -->
    <SearchForm @search="fetchList">
      <SearchItem title="姓名">
        <input type="text" v-model="searchQuery.name">
      </SearchItem>
    </SearchForm>
    <!-- 表格 -->
    <TableGrid :list="list" :pager="pager"/>
  </div>
</template>

<script setup>
import useList from './use-list'
const {
  components: {
    SearchForm,
    SearchItem,
    TableGrid
  },
  list,
  fetchList,
  searchQuery,
} = useList()
</script>

参考文档

上一篇下一篇

猜你喜欢

热点阅读