从 0 到 1 实现 react - 9.onChange 事件以及受控组件

React 框架的核心内容 项目地址 从一个疑问点开始 接上一章 HOC 探索 抛出的问题 ———— react 中的 onChange 事件和原生 DOM 事件中的 onchange 表现不一致,举例说明如下: // React 中的 onChange 事件 class App extends Component { constructor(props) { super(props) this.onChange = this.onChange.bind(this) } onChange(e) { console.log('键盘松开立刻执行') } render() { return ( ) } } /*--------------分割线---------------*/ // 原生 DOM 事件中的 onchange 事件: document.getElementById('test').addEventListener('change', (e) => { console.log('键盘松开以后还需按下回车键或者点下鼠标才会触发') }) 拨云见雾 我们来看下 React 的一个 issue React Fire: Modernizing React DOM。有两点信息和这篇文章的话题相关。 Drastically simplify the event system Migrate from onChange to onInput and don’t polyfill it for uncontrolled components 从这两点内容我们可以得知下面的信息: React 实现了一套合成事件机制,也就是它的事件机制和原生事件间会有不同。比如它目前 onChange 事件其实对应着原生事件中的 input 事件。在这个 issue 中明确了未来会使用 onInput 事件替代 onChange 事件,并且会大幅度地简化合成事件。 有了以上信息后,我们对 onChange 事件(将来的 onInput 事件)的代码作如下更改: function setAttribute(dom, attr, value) { ... if (attr.match(/on\w+/)) { // 处理事件的属性: let eventName = attr.toLowerCase().substr(2) if (eventName === 'change') { eventName = 'input' } // 和现阶段的 react 统一 dom.addEventListener(eventName, value) } ... } 自由组件以及受控组件 区分自由组件以及受控组件在于表单的值是否由 value 这个属性控制,比较如下代码: const case1 = () => // 此时输入框内可以随意增减任意值 const case2 = () => // 此时输入框内显示 123,能随意增减值 const case3 = () => // 此时输入框内显示 123,并且不能随意增减值 case3 的情形即为简化版的受控组件。 受控组件的实现 题目可以换个问法:当 input 的传入属性为 value 时(且没有 onChange 属性),如何禁用用户的输入事件的同时又能获取焦点? 首先想到了 html 自带属性 readonly、disable,它们都能禁止用户的输入,但是它们不能满足获取焦点这个条件。结合前文 onChange 的实现是监听 input 事件,代码分为以下两种情况: 1.dom 节点包含 value 属性、onChange 属性 2.dom 节点包含 value 属性,不包含 onChange 属性 代码如下: function vdomToDom(vdom) { ... if (vdom.attributes && vdom.attributes.hasOwnProperty('onChange') && vdom.attributes.hasOwnProperty('value')) { // 受控组件逻辑 ... dom.addEventListener('input', (e) => { changeCb.call(this, e) dom.value = oldValue }) ... } if (vdom.attributes && !vdom.attributes.hasOwnProperty('onChange') && vdom.attributes.hasOwnProperty('value')) { // 受控组件逻辑 ... dom.addEventListener('input', (e) => { dom.value = oldValue }) ... } ... } 可以发现它们的核心都在这段代码上: dom.addEventListener('input', (e) => { changeCb.call(this, e) dom.value = oldValue }) 区别是当有 onChange 属性 时,能提供相应的回调函数 changeCb 通过事件循环机制改变表单的值。看如下两个例子的比较: const App = () => 效果如下: class App extends Component { constructor() { super() this.state = { num: 123 } this.change = this.change.bind(this) } change(e) { this.setState({ num: e.target.value }) } render() { return (
) } } 这段代码中的 change 函数即上个段落所谓的 changeCb 函数,通过 setState 的事件循环机制改变表单的值。 效果如下: 至此,模拟了受控组件的实现。 作者:牧云云 出处:http://www.cnblogs.com/MuYunyun/" 本文版权归作者和博客园所有,欢迎转载,转载请标明出处。 如果您觉得本篇博文对您有所收获,请点击右下角的 [推荐],谢谢! 分类: Reacthttps://www.cnblogs.com/MuYunyun/p/9669679.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信