Синтаксический сахар ES6, который вы должны собрать — хитрости оператора распространения

ECMAScript 6 Omi
Синтаксический сахар ES6, который вы должны собрать — хитрости оператора распространения

→→→ Исходный адрес

Spread Operator — мой любимый синтаксический сахар.Нет никого, а также он наиболее широко используется в сценариях приложений.Сценарии и приемы использования приведены ниже.

что соответствуетПлагин Бабель, Конечно, при непосредственном использовании машинописного текста или непосредственного использования omi-cli эта функция встроена и может использоваться напрямую.

Не использует Apply

Применить и вызов могут выполнять функции, изменяя его для выполнения, например:

function add(a, b){
  return a + b
}

Предполагая, что параметр сцены передается в виде массива, традиционный подход таков:

const args = [11, 12]
add.apply(null, args)

или

const args = [11, 12]
add.call(null, args[0], args[1])

После использования оператора спреда:

const args = [11, 12]
add(...args)

Результат компиляции babel:

function add(a, b) {
  return a + b;
}
var args = [11, 12];
add.apply(undefined, args);

Общие сценарии включают в себя:

const arr = [1, 2, 3, 4, 5]
Math.min(...arr)  //求最小值
Math.max(...arr)  //求最大值

Результат компиляции babel:

var arr = [1, 2, 3, 4, 5];
Math.min.apply(Math, arr); //求最小值
Math.max.apply(Math, arr); //求最大值

Поскольку количество параметров Math.min и Math.max не ограничено, этот сценарий очень подходит для использования оператора распространения.

Объединить массивы

Сначала посмотрите на синтаксис массива push:

array.push(item1, item2, ...., item3)

Видно, что параметры, полученные методом push, также являются неопределенными, поэтому его можно использовать для реализации функции объединения массивов:

arr1.push(...arr2)

Или объединиться на передний план:

arr1.unshift(...arr2)

Также возможно выполнить прямое декларативное слияние:

const arr1 = [2, 3]
const arr2 = [1, ...arr1, 4]  //arr2 相当于 [1, 2, 3, 4]

Например:

const a = [1, 2]
a.push(...[3, 4, 5])   //[1,2,3,4,5]

После компиляции babel:

var a = [1, 2];
a.push.apply(a, [3, 4, 5]);

Преобразование аргументов или NodeList в массив

[...document.querySelectorAll('div')]

После компиляции bebel:

function _toConsumableArray(arr) { 
  if (Array.isArray(arr)) { 
    for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { 
      arr2[i] = arr[i]; 
    } 
    return arr2; 
  } else { 
    return Array.from(arr); 
  } 
}

[].concat(_toConsumableArray(document.querySelectorAll('div')));

Преобразование аргументов непосредственно в массив:

var myFn = function(...args) {
  console.log(args.forEach) //ƒ forEach() { [native code] }
  console.log(arguments.forEach) //undefined
}
myFn()

После компиляции babel:

var myFn = function myFn() {
  for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
    args[_key] = arguments[_key];
  }

  console.log(args.forEach); //ƒ forEach() { [native code] }
  console.log(arguments.forEach); //undefined
};
myFn();

быстрое назначение

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }

После компиляции babel:

function _objectWithoutProperties(obj, keys) { 
  var target = {};
   for (var i in obj) { 
     if (keys.indexOf(i) >= 0) continue; 
     if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; 
     target[i] = obj[i];
  } 
  return target;
}

var _x$y$a$b = { x: 1, y: 2, a: 3, b: 4 },
    x = _x$y$a$b.x,
    y = _x$y$a$b.y,
    z = _objectWithoutProperties(_x$y$a$b, ["x", "y"]);

Распространяйте реальный бой

react useа такжеomi use

 return [list, {
    set,
    push: (entry) => set([...list, entry]),
    filter: (fn) => set(list.filter(fn)),
    sort: (fn?) => set([...list].sort(fn)),
  }];
};
  <button onClick={() => setItems([...items, { text: 'new item' }])}>
    add
  </button>
  <button onClick={() => setItems([])}>empty</button>

Конечно, мне не нравится определять компоненты таким образом, поэтому я не стал добавлять подобные функции в omio.

Omi extractclass

import { classNames, extractClass } from 'omi'

define('my-element', class extends WeElement {
  render(props) {
    //extractClass will take out this class/className from props and merge the other classNames to obj
    const cls = extractClass(props, 'o-my-class', {
      'other-class': true,
      'other-class-b': this.xxx === 1
    })

    return (
      <div {...cls} {...props}>
        Test
      </div>
    )
  }
})

extractClassЭто просто артефакт для написания компонентов пользовательского интерфейса.Этот метод извлекает class или className реквизита и объединяет его с библиотекой, похожей на classNames. Наконец добавлено в JSX через оператора распространения.

Кнопка Omiu в действии

import { define, WeElement, extractClass } from 'omi'
import css from './_index.css'

define('o-button', class extends WeElement {
  static defaultProps = {
    disabled: false,
    type: 'primary',
    size: 'normal'
  }

  css() {
    return css
  }

  render(props) {
    //提取 class,并从 props 中去掉
    let cls = extractClass(props) || {}
    const {
      component,
      type,
      size,
      plain,
      children,
      ...others
    } = this.props


    const Component = component
      ? component
      : this.props.href || type === 'vcode'
        ? 'a'
        : 'button'
    cls =
      type === 'vcode'
        ? extractClass(cls, 'weui-vcode-btn')
        : extractClass(cls, {
          'weui-btn': true,
          'weui-btn_mini': size === 'small',
          'weui-btn_primary': type === 'primary' && !plain,
          'weui-btn_default': type === 'default' && !plain,
          'weui-btn_warn': type === 'warn',
          'weui-btn_plain-primary': type === 'primary' && plain,
          'weui-btn_plain-default': type === 'default' && plain,
          'weui-btn_disabled': this.props.disabled && !plain,
          'weui-btn_plain-disabled': this.props.disabled && plain
        })

    return (
      <Component {...others} {...cls}>
        {children}
      </Component>
    )
  }
})

Исходный код ExtractClass

export function extractClass() {
  //提取第一个参数 props 和剩余的 args
  const [props, ...args] = Array.prototype.slice.call(arguments, 0)
  if (props.class) {
    args.unshift(props.class)
    delete props.class
  } else if (props.className) {
    args.unshift(props.className)
    delete props.className
  }
  if (args.length > 0) {
    return { class: classNames.apply(null, args) }
  }
}

Вы можете видеть, что сам extractClass также использует Spread Operator, который действительно везде.

Справочная документация