栅格系统是布局常用元素,关于其对应的CSS实现,我在讲述bootstrap3的栅格bootstrap4的栅格时已经讲过了,我这里只说明element-ui是如何把栅格系统组件化的。

row

element-ui直接采用了render函数的写法,毕竟这个组件不是很复杂:

export default {
  name: 'ElRow',
  // 用于给col组件判断是否是row组件的
  componentName: 'ElRow',
  props: {
    // 可以自定义标签类型
    tag: {
      type: String,
      default: 'div'
    },
    gutter: Number,
    type: String,
    justify: {
      type: String,
      default: 'start'
    },
    align: {
      type: String,
      default: 'top'
    }
  },
  computed: {
    style() {
      const ret = {};

      if (this.gutter) {
        ret.marginLeft = `-${this.gutter / 2}px`;
        ret.marginRight = ret.marginLeft;
      }

      return ret;
    }
  },

  render(h) {
    return h(this.tag, {
      // 其实class也可以作为computed属性
      class: [
        'el-row',
        this.justify !== 'start' ? `is-justify-${this.justify}` : '',
        this.align !== 'top' ? `is-align-${this.align}` : '',
        { 'el-row--flex': this.type === 'flex' }
      ],
      style: this.style
    }, this.$slots.default);
  }
};

row组件的render函数用jsx可以这么写:

render(h){
    const Tag = this.tag;
    return (
        <Tag
            class={this.cls}
            style={this.style}
        >
            {this.$slots.default}
        </Tag>
    );
}

col

对于col组件来说,一个难题是如何获取gutter,因为gutter是row组件的prop而不是col组件的prop。

  computed: {
    gutter() {
      let parent = this.$parent;
      while (parent && parent.$options.componentName !== 'ElRow') {
        parent = parent.$parent;
      }
      return parent ? parent.gutter : 0;
    }
  },

这个有点类似于provide/inject的实现,就是不断向上查找到最近的row组件,然后获取row组件的gutter属性。如果要用provide/inject的话,row组件provide gutter属性并不是一个好主意,因为即使利用getter ,inject的时候也只是一个简单值,并不是响应式的,一个比较常见的解决方案是provide整个组件实例。

provide(){
  return {
    // provide整个组件实例
    row:this
  }
}

考虑到col组件只是一个布局展示性质的组件,没有自身状态和生命周期,可以考虑改写成functional component,但是此时parent指向和有状态组件是不一致的,改写的时候需要把gutter作为prop传递给col组件。

results matching ""

    No results matching ""