资讯专栏INFORMATION COLUMN

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

dongxiawu / 2747人阅读

摘要:比如它目前事件其实对应着原生事件中的事件。在这个中明确了未来会使用事件替代事件,并且会大幅度地简化合成事件。效果如下至此,模拟了受控组件的实现。

该系列文章在实现 cpreact 的同时理顺 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(/onw+/)) {        // 处理事件的属性:
    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 的事件循环机制改变表单的值。

效果如下:

至此,模拟了受控组件的实现。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97880.html

相关文章

  • React受控与非受控组件

    摘要:首次发表在个人博客受控组件或都要绑定一个事件每当表单的状态发生变化都会被写入组件的中这种组件在中被称为受控组件在受控组件中组件渲染出的状态与它的或者向对应通过这种方式消除了组件的局部状态是的应用的整个状态可控官方同样推荐使用受控表单组件总结 首次发表在个人博客 受控组件 { this.setState({ value: e.target.val...

    wenhai.he 评论0 收藏0
  • React深度编程:受控组件与非受控组件

    摘要:受控组件与非受控组件在官网与国内网上的资料都不多,有些人觉得它可有可不有,也不在意。受控组件与非受控组件是处理表单的入口。认为不能单独存在,需要与等控制的属性或事件一起使用。它们共同构成受控组件,受控是受的控制。 受控组件与非受控组件在官网与国内网上的资料都不多,有些人觉得它可有可不有,也不在意。这恰恰显示React的威力,满足不同规模大小的工程需求。譬如你只是做ListView这样简...

    wpw 评论0 收藏0
  • 掌握react,这一篇就够了

    摘要:小明小明儿子,可以看到组件显示了父组件的。小明受控组件和非受控组件受控组件和非受控组件这些都是指的表单组件,当一个表单的值是通过改变的而不是通过是受控组件,否则就是非受控组件。 react众所周知的前端3大主流框架之一,由于出色的性能,完善的周边设施风头一时无两。本文就带大家一起掌握react。 jsx语法 前端MVVM主流框架都有一套自己的模板处理方法,react则使用它独特的jsx...

    Enlightenment 评论0 收藏0
  • 翻译 | 玩转 React 表单 —— 受控组件详解

    摘要:受控输入框只会显示通过传入的数据。例如,数组中的元素将会渲染三个单选框或复选框。属性接收一个布尔值,用来表示组件是否应该被渲染成选中状态。 原文地址:React.js Forms: Controlled Components 原文作者:Loren Stewart 译者:小 B0Y 校对者:珂珂君 本文涵盖以下受控组件: 文本输入框 数字输入框 单选框 复选框 文本域 下拉...

    big_cat 评论0 收藏0
  • 翻译 | 玩转 React 表单 —— Refs 的运用

    摘要:函数更新属性,进而更新元素的值。由于箭头函数存在于父组件中,所以中的指向父组件。一旦表单被提交,的值就被设置为。遗憾的是,没有节点是包含了集合的。在这种情况下,这个节点列表包含三个节点和被选中的值。 原文地址:React Forms: Using Refs 原文作者:Loren Stewart 译者:萌萌 校对者:小 boy React 提供了两种从 元素中获取值的标准方法。第一...

    gougoujiang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<