专栏首页Super 前端Thinking--Normalize思想在前端中的应用

Thinking--Normalize思想在前端中的应用

Thinking系列,旨在利用10分钟的时间传达一种可落地的编程思想。

Normalize

标准化:Normalize

发组件过程中,为了提高组件的灵活性,我们通常需要支持多种传参格式,如何优雅的控制和组件内部解耦变得尤为重要!

示例: Vue的 clip-board 指令,支持两种传参方式。

  • 如果是字符串,则为要拷贝的文本内容
  • 如果是对象,对象中的text属性,为要拷贝的文本内容
<div v-clip-board="txt"></div>
<div v-clip-board="{text: 'txt', success, error}"></div>

传统写法

const _noop = function () { return {} }
const ClipBoard = require('clipboard')
export default {
  name: 'clip-board',
  hooks: {
    bind: function (el, binding, vnode) {
      const clipboard = new ClipBoard(el, {
        action () { return binding.arg === 'cut' ? 'cut' : 'copy' }
      })
      // 判断是否为对象,并解构对象属性
      if (typeof (binding.value) === 'object') { 
        let { success = _noop, error = _noop } = binding.value
        clipboard.on('success', e => { 
          success()
        })
        clipboard.on('error', e => {
          error()
        })
      }
      el._clipboard = clipboard
    },
    update (el, binding) {
      el._clipboard.text = function () {
        // 判断是否为对象,处理相关值
        return typeof (binding.value) === 'string' ? binding.value : binding.value.value
      }
    },
    unbind (el, binding) {
      el._clipboard.destroy()
      delete el._clipboard
    }
  }

如果增加第三种参数支持,如数组格式,该如何处理?bindupdate 方法中都需要增加判断分支。

Normalize后

const _noop = function () {}
// 集中化处理参数
const normalizeProps = function (param) {
  let obj = {
    text: '',
    action: param.arg ? param.arg : 'copy', 
    success: _noop,
    error: _noop
  }
  let type = Object.prototype.toString.call(param.value).match(/^\[object (.*)\]$/)[1].toLowerCase()
  switch (type) {
    case 'string':
      obj.text = param.value
      break
    case 'object':
      obj = Object.assign({}, obj, param.value)
      break
    default:
      break
  }
  return obj
}

const ClipBoard = require('clipboard')
export default {
  name: 'clip-board',
  hooks: {
    bind: function (el, binding, vnode) {
      let { action, success, error } = normalizeProps(binding)
      const clipboard = new ClipBoard(el, {
        action () { return action }
      })
      clipboard.on('success', e => {
        success()
      })
      clipboard.on('error', e => {
        error()
      })
      el._clipboard = clipboard
    },
    update (el, binding) {
      el._clipboard.text = function () {
        return normalizeProps(binding)['text']
      }
    },
    unbind (el, binding) {
      el._clipboard.destroy()
      delete el._clipboard
    }
  }
}

优势:

  1. 统一了判断入口,核心代码省掉了不必要的分支判断,简单明了;
  2. 后续需要增加其他格式属性时,核心代码无需修改,只需调整 normalize 函数。

哪里还有类似的场景出现?

以 Vue 中 Props 为例,进行说明 https://github.com/vuejs/vue/blob/dev/src/core/util/options.js#L298

props: ["propA"]
props: {
    propB: Object,
    propC: {
    	type: String
    }
}

延伸

外观设计模式:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • requireJS

    requireJS(http://www.requirejs.cn/)是一个JavaScript模块加载器。它非常适合在浏览器中使用,使用RequireJS加...

    奋飛
  • Vue基础:数据绑定

    注意:当v-bind:style使用需要特定前缀的CSS属性时,如transform,Vue.js会自动侦测并添加相应的前缀。

    奋飛
  • 单页应用优化--懒加载

    最近查阅了一些帖子,发现了一个极其强大的方法,其兼容性有待提高~~(但已有相关的的Polyfill方式)

    奋飛
  • 2-3 T-SQL函数

    在Transact-SQL语言中,函数被用来执行一些特殊的运算以支持SQL Server的标准命令。SQL Server包含多种不同的函数用以完成各种工作,每一...

    py3study
  • Java的包机制以及import、static import的用法详解(看这篇就够了)

    com.a、com.a.b和com.a.b.c三者没有包含关系,是三个完全独立的包

    bboy枫亭
  • C语言---头文件

    今天说一个我在工作时候发现的一个细节,可能大家都已经清楚的知道了,我就在这里记录一下吧。 不想看过程的直接去文末看结论吧。

    HeaiKun
  • 梯度下降算法中的偏导公式推导

    前言:最近在跟着吴恩达老师(Andrew Ng)的视频课程学习机器学习,该视频是2014年拍的,虽然有点老,但理论却并不过时,是非常经典的机器学习入门教程,也正...

    阿波张
  • 猿实战11——类目属性绑定之el-tree的使用

    猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,变身猿人找到...

    山旮旯的胖子

扫码关注云+社区

领取腾讯云代金券