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
    }
}

normalize设计模式

延伸

外观设计模式:
外观设计模式.

发布了256 篇原创文章 · 获赞 868 · 访问量 118万+

猜你喜欢

转载自blog.csdn.net/ligang2585116/article/details/90738882