最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Vue 之 More in js

    正文概述 掘金(iel)   2021-06-17   433

    前言

    在说 More in js 之前,想必大家对 ReactAll in js 都不陌生,各位看官莫被干扰,本文与 React 无关。More in js 为笔者开发过程中的一些实例尝试,可能大家都有过类似的开发经历,但少有人思考这么做的价值。

    Vue 之 More in js

    SFC 组件结构

    讲到 Vue 的 SFC 组件结构,大家首先想到的一定是 template script style 三部曲。实际表现形式如下:

    <template>
        ...
    </template>
    
    <script>
        ...
    </script>
    
    <style>
        ...
    </style>
    

    上面的代码就是 VueSFC 基础结构了,那这跟我们的 More in js 又有啥关系呢?

    SFC 常见问题

    我们通常在业务组件开发时,避免不了出现复杂布局情况,组件嵌套(一层又一层,层层不一样),此时再加上业务逻辑的处理,代码行数轻轻松松破 1000+

    那么在维护或开发此类代码时,可能就是为了加一个属性导致我们在 templatescript 之间反复横跳,开发体验较差,也带来了额外的时间成本。(此时某位暴躁老哥已经开始砸键盘了!)

    Vue 之 More in js

    上图是笔者开发中的一个画布组件,其代码行数不算样式部分也突破了 2000+,对于正在修改业务逻辑的我突然需要给视图组件加个属性,直接促使肾上腺素飙升!

    灵感来源

    对于上述问题的解决方案是在业务组件封装时产生的灵感。

    通常 UI 组件库的基础组件并不能满足我们复杂的业务需求时,会对齐进行二次封装,那么对于源组件的 propsevents 我们也是需要暴露给外界来降低上手成本,只针对该处的场景提供便利性,纵享丝滑体验。

    例如:

    <template>
      <Button
        class="async-button"
        ref="main"
        v-bind="mergeProps"
        :loading="loading"
        @click.prevent="onClick"
      >
        <slot></slot>
      </Button>
    </template>
    
    <script>
    import { omit, merge } from 'lodash'
    
    export default {
      name: 'AsyncButton',
      props: {
        /**
         * 使用原始 Button 事件
         * @default false
         */
        useRaw: { type: Boolean, default: false }
      },
      data() {
        return {
          loading: false
        }
      },
      computed: {
        mergeProps() {
          const defaultProps = { type: 'primary' }
          return omit(merge(defaultProps, this.$attrs), 'loading')
        }
      },
      methods: {
        /**
         * 处理点击事件。
         */
        onClick(e) {
          // useRaw: true 使用原始单击事件,false 使用异步单击事件
          if (this.useRaw) {
            this.$emit('click', e)
          } else {
            this.loading = true
            this.$emit('click', () => (this.loading = false), e)
          }
        }
      }
    }
    </script>
    

    上面代码是对 Button 组件做的一层简单封装,让使用者能够在点击时自动启动加载状态,在需要时通过回调函数来关闭加载状态。

    对于源 Button 组件的 props 通过 Vue 提供的 v-bind$attrs 实现属性穿透,那么反过来我们思考下是否可以把该方式应用到业务组件开发中?

    答案是可以的。

    More in js

    提出的 More in js 概念就是为了让 Vue 开发者能够更好地专注于业务逻辑部分的处理,配合 IDE 的定义跳转功能,可以相对的优化上述问题。

    <template>
      <SpecialTabs class="data-point-tabs" left-label="上传文件" right-label="已上传的文件列表">
        <!-- upload start -->
        <template slot="left">
          <SingleUpload ref="singleUpload" v-bind="singleUpload" />
        </template>
        <!-- upload end -->
        
        <!-- table start -->
        <template slot="right">
          <!-- table -->
          <Table class="file-table" v-bind="table" @hook:created="loadTableData" />
    
          <!-- modal start -->
          <Modal v-bind="modal" v-model="modal.show" transfer>
            <!-- modal footer -->
            <template slot="footer">
              <Button @click="toggleModal(false)">取消</Button>
              <Button v-bind="confirmBtn" @click="submitForm">确定</Button>
            </template>
    
            <!-- edit form -->
            <EditForm
              ref="editFormRef"
              :key="`edit-form_${updateFormFlag}`"
              :info="table.singleSelected"
              @on-validated="handleValidated"
              @on-submitted="handleSubmitted"
            ></PointForm>
          </Modal>
          <!-- modal end -->
        </template>
        <!-- table end -->
      </SpecialTabs>
    </template>
    
    <script>
    import SpecialTabs from '@/components/SpecialTabs'
    import SingleUpload from '@/components/SingleUpload'
    import { dataPointColumns } from './entity/data-point'
    import DeleteMixin from '@/mixins/delete'
    import EditForm from './components/edit-form.vue'
    import { showErrorMessage } from '@/util/error'
    
    export default {
      name: 'DataPoint',
      mixins: [DeleteMixin],
      components: { SpecialTabs, SingleUpload, EditForm },
      data() {
        return {
          singleUpload: {
            autoUpload: true,
            loading: false,
            uploadRequest: this.uploadRequest,
            beforeUpload: this.handleBeforeUpload
          },
          table: {
            border: true,
            loading: false,
            disabledHover: true,
            columns: dataPointColumns.call(this),
            data: [],
            singleSelected: {},
            actionOptions: [...]
          },
          modal: {
            title: '配置表单',
            maskClosable: false,
            show: false
          },
          confirmBtn: {
            type: 'primary',
            loading: false
          },
          updateFormFlag: 0
        }
      },
      computed: {
        /**
         * DeleteMixin
         */
        deleteOption() {
          return {
            deleteUrl: '/db_table/delete',
            method: 'delete',
            loading: true,
            params: (selection) => ({ table_name: selection[0].table_name }),
            afterDelete: (flag) => flag && this.loadTableData()
          }
        }
      },
      methods: {
        ...
      }
    }
    </script>
    

    上述代码是对 More in js 的一次尝试,组件的属性对象显示声明在 data 中,通过 v-bind 来动态绑定到模板上,能够提升代码的阅读性,让开发者更加专注业务逻辑层,对于视图层只关注在布局即可。

    Vue 之 More in js

    配合 IDE 的定义跳转功能,能够轻松实现对视图层组件的属性控制及添加,减少代码横跳次数,提升开发效率。

    Vue3 更优体验

    Vue2 中由于 options api 的结构,我们的组件开发通常在单文件中,不会对内部业务逻辑过于聚合,所以 More in js 方式只会解决单文件内部的代码横跳问题。

    但是在 Vue3hooks api 中,我们可以通过抽离业务逻辑到 @use/xxx 后,让视图层与逻辑层的代码高度聚合,使用 More in js 可以更好的维护组件状态,不需要频繁的切换文件来更新属性信息。

    // dp.vue
    <template>
      <SpecialTabs class="data-point-tabs" left-label="上传文件" right-label="已上传的文件列表">
        <!-- upload start -->
        <template slot="left">
          <SingleUpload ref="singleUploadRef" v-bind="singleUploadAttrs" />
        </template>
        <!-- upload end -->
        
        <!-- table start -->
        <template slot="right">
          <!-- table -->
          <Table class="file-table" v-bind="tableAttrs" @hook:created="loadTableData" />
    
          <!-- modal start -->
          <Modal v-bind="modal" v-model="modal.show" transfer>
            <!-- modal footer -->
            <template slot="footer">
              <Button @click="toggleModal(false)">取消</Button>
              <Button v-bind="confirmBtn" @click="submitForm">确定</Button>
            </template>
    
            <!-- edit form -->
            <EditForm
              ref="editFormRef"
              :key="`edit-form_${updateFormFlag}`"
              :info="tableAttrs.singleSelected"
              @on-validated="handleValidated"
              @on-submitted="handleSubmitted"
            ></PointForm>
          </Modal>
          <!-- modal end -->
        </template>
        <!-- table end -->
      </SpecialTabs>
    </template>
    
    <script setup>
    ...
    
    const { singleUploadAttrs, ... } = useUpload()
    const { tableAttrs, ... } = useTable()
    </script>
    
    
    // @use/upload.js
    ...
    
    export default function useUpload() {
        const singleUploadAttrs = reactive({
            autoUpload: true,
            loading: false,
            uploadRequest: uploadRequest,
            beforeUpload: handleBeforeUpload
        })
        
        function uploadRequest() {...}
        
        function handleBeforeUpload() {...}
        
        ...
        
        return { singleUploadAttrs, ... }
    }
    
    
    // @use/table.js
    ...
    
    export default function useTable() {
        const tableAttrs = reactive({
            border: true,
            loading: false,
            disabledHover: true,
            columns: dataPointColumns(),
            data: [],
            singleSelected: {},
            actionsOptions: [...]
        })
        
        function loadTableData() {
            ...
            
            tableAttrs.data = [...]
        }
        
        ...
        
        return { tableAttrs, ... }
    }
    

    Volar 体验提升

    随着 Vue3 的稳定,IDE 方面的插件也有了新的支持,官方维护的 Volar 脱颖而出,这里只重点说明 Volar 的编辑器拆分功能来让体验更加丝滑。

    Vue 之 More in js

    通过拆分编辑器,配合 More in js 方式,只需要关注左侧 hooks 代码即可让开发体验上升一个台阶。

    总结

    本次灵感主要解决开发时繁琐的代码横跳,从而找出更优的开发体验,但非最优体验,因人而异,请各位看官勿喷。有何问题,可评论区留言,谢谢!

    相逢即是缘,挥一挥手指,留下一个赞吧!(^▽^)

    Vue 之 More in js


    下载网 » Vue 之 More in js

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元