element源码分析系列4--Radio巧夺天公的设计思想

栏目: 编程工具 · 发布时间: 5年前

内容简介:学习就好比是座大山,人们沿着不同的路登山,分享着自己看到的风景。你不一定能看到别人看到的风景,体会到别人的心情。只有自己去登山,才能看到不一样的风景,体会更加深刻。一千个读者就有一千个哈姆雷特,但是莎士比亚心中的哈姆雷特肯定只有一个。就好比element源码只有一个,但每个人看到的都是不一样的风景。element源码解读是一个系列,每一个组件细腻的背后都能看到前端工程师付出的心血,本篇带来的是Element源码分析系列4-Radio(单选框)单选框这个组件看似简单,实则知识点众多,较为复杂,如果写一个htm

学习就好比是座大山,人们沿着不同的路登山,分享着自己看到的风景。你不一定能看到别人看到的风景,体会到别人的心情。只有自己去登山,才能看到不一样的风景,体会更加深刻。一千个读者就有一千个哈姆雷特,但是莎士比亚心中的哈姆雷特肯定只有一个。就好比element源码只有一个,但每个人看到的都是不一样的风景。element源码解读是一个系列,每一个组件细腻的背后都能看到前端工程师付出的心血,本篇带来的是Element源码分析系列4-Radio(单选框)

简介

单选框这个组件看似简单,实则知识点众多,较为复杂,如果写一个html的原生单选框,那确实很简单,但是封装一个完整的单选组件就不那么简单了。element团队在整个radio组件的设计和构思真可谓十分的细致,没有一行多余的代码。从基础的css到选择逻辑都无不彰显其巧夺天工的思想。

划重点

1、如何隐藏原始radio标签默认样式

我们都知道原生的radio标签很丑,样式在各个浏览器不统一,作为一个组件不可能就这样屈服,况且人这种物种总是希望统驾驭所有的物质之上,包括代码。所以必须自己实现所有radio按钮的样式,那么如何自己实现一个可控制的radio标签呢?看element是怎么实现的。

element源码分析系列4--Radio巧夺天公的设计思想

看图不难分析出radio组件的html样式,整个大盒子被一个laber标签包裹着,laber里分为两个span,第一个span是用来展示选择按钮的,第二个span是来描述选项的。第一个span里应该包括input(用来做radio)和span(隐藏真正的input)两个标签。其相关的html结构如下:

<label className='el-radio'>
    <span>
      <span className="el-radio__inner"></span>
      <input 
        type="radio"
        className="el-radio__original"
      />
    </span>
    <span className="el-radio__label">
      {children || value}
    </span>
</label>
复制代码

问题一:如何做到隐藏原始radio标签默认样式?作者巧用opacity:0,真正的input透明度为0,且是绝对定位脱离文档流,因此不占空间且我们看不到,注意不是display:none或者visibility:hidden,如果是none或者hidden的话则无法触发鼠标点击了,所以只有opacity:0才能达到目的.

.el-radio__original {
    opacity: 0;
    outline: 0;
    position: absolute;
    z-index: -1;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: 0;
}
复制代码

2、如何点击选择按钮展示不同的状态

如何做到点击旋钮显示不同的状态。通过radio标签可分析出,点击即可以理解为一个事件(这里用onChange表示)。通过点击事件传递一个props值(checked)显示不同的状态。所以在input上一定会有一个事件和一个所要传递的状态。

<input 
    type="radio"
    className="el-radio__original"
    checked={checked}  // 传递的状态
    onChange={this.onChange.bind(this)}   // 事件
 />
复制代码

那么接下来就是定义事件了,其核心代码为:

constructor(props) {
    super(props);
    this.state = {
      checked: this.getChecked(props)  // 定义一个state,受props影响
    };
  }
  componentWillReceiveProps(props) {
    const checked = this.getChecked(props);  
    if (this.state.checked !== checked) {   // 维持每次点击时只选中一个
      this.setState({ checked });
    }
  }
  getChecked(props) {
    return  Boolean(props.checked)  // 根据传递的props,输出true/false
  }
  onChange(e) {
    const checked = e.target.checked;  // 定义被点击项的checked为true
    if (checked) {
      if (this.props.onChange) {
        this.props.onChange(this.props.value);  // 向外暴露一个onChange事件并携带value值
      }
    }
    this.setState({ checked }); // 更新被点击项的state为true
  }
复制代码

如果你对上述描述的还是雨里雾里,那么下面这张图可以更好的帮组你理解element-radio标签事件的逻辑:

element源码分析系列4--Radio巧夺天公的设计思想

从图中我们可以看出,radio是如何做到点击改变状态,并且又如何维护每次点击完后radio的状态。

  • 传入checked作为props决定每个radio的状态
  • 根据传入的props,定义一个内部的state,跟props的checked保持一致
  • 点击事件改变当前的radio的状态,更新state中的checked,并且向外传递一个value
  • 外面接受到传来的value,重新定义props
  • 通过生命周期函数更新内部的state,让其保持每个radio一致

3、Radio.Group如何做到单选框组

单选框组故名思议是将所有的radio包裹一层,由最外层原始事件来决定每个radio的状态。故需要用到React的两个API:React.Children.map、React.cloneElement

技术扩展:

  • React.Children 提供了用于处理 this.props.children 不透明数据结构的实用方法。
React.Children.map(children, function[(thisArg)])

在 children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg。如果 children 是一个数组,它将被遍历并为数组中的每个子节点调用该函数。如果子节点为 null 或是 undefined,则此方法将返回 null 或是 undefined,而不会返回数组。

  • React.cloneElement: 以 element 元素为样板克隆并返回新的 React 元素。返回元素的 props 是将新的 props 与原始元素的 props 浅层合并后的结果。
React.cloneElement(element, [props], [...children])

先了解这两个API,在来看看element中Radio.Group的源码就很简单来。

<div ref='RadioGroup' className='el-radio-group'>
    {
      React.Children.map(this.props.children, element => {
        if (!element) {
          return null
        }

        return React.cloneElement(element, Object.assign({}, element.props, {
          onChange: this.onChange.bind(this),
          value: this.props.value,
        }))
      })
    }
</div>
复制代码

通过遍历所有的radio组件,克隆出相应的radio组件,并为其附上radio的一些属性,包括方法和value。

结语

纵观整个radio的设计和实现,每个设计的过程都十分的微妙,尤其是radio如何更新状态,在平时业务中,我们也经常会遇到这种需求,但是真正的实现起来却没有这么简洁。源码的学习或多或少可以让我们增强自己的代码能力和业务能力。那么跟随我的脚步,带你一步一步解析整个element源码的奇思妙想。山不再高,有仙则灵;水不在深,有心则成。后续将推出更多源码解析文章。源码请:point_down:这里 element-radio源码


以上所述就是小编给大家介绍的《element源码分析系列4--Radio巧夺天公的设计思想》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

A Project Guide to UX Design

A Project Guide to UX Design

Russ Unger、Carolyn Chandler / New Riders Press / 2009-3-23 / USD 39.99

"If you are a young designer entering or contemplating entering the UX field this is a canonical book. If you are an organization that really needs to start grokking UX this book is also for you. " -......一起来看看 《A Project Guide to UX Design》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具