React-引领未来的用户界面开发框架-读书笔记(三)

前端之家收集整理的这篇文章主要介绍了React-引领未来的用户界面开发框架-读书笔记(三)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

第8章 DOM操作

多数情况下,React的虚拟DOM足以用来创建你想要的用户体验,而根本不需要直接操作底层真实的DOM。然而也有一些例外。最常见的场景包括:需要与一个没有使用React的第三方类库进行整合,或者执行一个React没有原生支持的操作。

访问受控的DOM节点

想要访问React控制的DOM节点,首先必须能够访问到负责这些DOM的组件。这可以通过为子组件添加一个ref属性来实现。

render () {
    return@H_502_12@ (
        <canvas ref@H_502_12@="mainCanvas"@H_502_12@ />
    )
}

这样就可以通过this.refs.mainCanvas访问到<canvas组件。

⚠️必须保证赋给每个子组件的ref值在所有子组件中是唯一的;否则操作就会失效。

可以通过getDOMNode()方法访问到底层的DOM节点。

⚠️不可以在render方法中这样做。因为这时底层的DOM可能不是最新的(甚至尚未创建)

尽管refs和getDOMNode很强大,但请在没有其他的方法能够实现你需要的功能时再去选择它们。使用它们会成为React在性能优化上的障碍,并且增加应用的复杂性。

componentDidMount方法只会为每个DOM节点调用一次。

如果在componentDidMount方法内导致了DOM节点无法被移除,有可能导致内存泄漏或者其他的问题。如果你担心这一点,请在componentWillUnmount监听器,用于在组件的DOM节点移除时清理它自身。

第9章 表单

在React中,表单组件有两种类型:约束组件和无约束组件

无约束组件

给定一个HTML的<input/>一个值,它的值是可以改变的。这正是无约束组件名称的由来,因为表单组件的值是不受React控制的。

submitHandler = (event@H_502_12@) => {
    event@H_502_12@.preventDefault();
    var@H_502_12@ hellTo = this@H_502_12@.refs.hellTo.getDOMNode().value@H_502_12@;
    alert(hellTo)
}
render () {
    return@H_502_12@ (
        <form onSubmit={this@H_502_12@.submitHandler}>
            <input ref@H_502_12@="hellTo"@H_502_12@ type="text"@H_502_12@ defaultValue="Hello World!"@H_502_12@ />
            <button type="submit"@H_502_12@>Speak</button>
        </form>
    )
}

无约束组件可以用在基本的无需任何验证或者输入控制的表单中。

约束组件

约束组件,表单的状态交由React组件控制,状态值被存储在React组件的state中。

constructor(props) {
    super@H_502_12@(props);
    this@H_502_12@.state = {
        helloTo = 'Hello World!'@H_502_12@
    }
}
handleChange@H_502_12@ = (event)@H_502_12@ =>@H_502_12@ {
    this@H_502_12@.setState({
        helloTo@H_502_12@: event.target.value
    })
}
submitHandler@H_502_12@ = (event)@H_502_12@ =>@H_502_12@ {
    event.preventDefault();
    alert(this@H_502_12@.state.helloTo)
}
render () {
    return@H_502_12@ (
        <form onSubmit={this@H_502_12@.submitHandler}>
            <input ref="text"@H_502_12@ onChange={this@H_502_12@.handleChange} />
            <button type="submit"@H_502_12@>Speak</button>
        </form>
    )
}

表单事件

React支持所有HTML事件。这些事件遵循驼峰命名的约定,且会被转成合成事件。

所有合成事件都提供了event.target来访问触发事件的DOM节点。

Label

由于for是JavaScript的保留字,所以我们无法把它作为一个对象的属性

jsx

<label htmlFor="name"@H_502_12@>Name@H_502_12@:</label>@H_502_12@

javascript

React@H_502_12@.DOM@H_502_12@.label@H_502_12@({htmlFor@H_502_12@:"name"@H_502_12@,"Name"@H_502_12@})@H_502_12@@H_502_12@;@H_502_12@

渲染后:

<label for@H_502_12@=:</label>@H_502_12@

文本框和Select

React对<textarea/><select/>的接口做了一些修改,提升了一致性,让它们操作起来更容易。

<textarea/>被改的更像<input/>了,允许我们设置value和defaulteValue。

//非约束的
<textareadefaultValue@H_502_12@ ="HelloWorld"@H_502_12@ />@H_502_12@
//约束的
<textareavalue={this.state.helloTo@H_502_12@ } onChange@H_502_12@ ={this.handleChange}@H_502_12@ />@H_502_12@

//非约束的
<selectdefaultValue="8"@H_502_12@>@H_502_12@
    <option@H_502_12@ value@H_502_12@="A"@H_502_12@>@H_502_12@First Option</option@H_502_12@>@H_502_12@
    <option@H_502_12@ value@H_502_12@="B"@H_502_12@>@H_502_12@Second Option</option@H_502_12@>@H_502_12@
    <option@H_502_12@ value@H_502_12@= "C@H_502_12@">@H_502_12@Third Option</option@H_502_12@>@H_502_12@
</select@H_502_12@>@H_502_12@
//约束的
<selectvalue@H_502_12@ ={this.state.helloTo}@H_502_12@ onchange@H_502_12@={this.handleChange}@H_502_12@>@H_502_12@
    <option@H_502_12@ value@H_502_12@="A"@H_502_12@>@H_502_12@FirstOption </option@H_502_12@>@H_502_12@
    <option@H_502_12@ value@H_502_12@="B"@H_502_12@>@H_502_12@Second Option </option@H_502_12@>@H_502_12@
    <option@H_502_12@ value@H_502_12@="C"@H_502_12@>@H_502_12@Third Option</option@H_502_12@>@H_502_12@
</select@H_502_12@>@H_502_12@

React支持都选selce他,需要给value的defauletValue传递一个数组,如:defaultValue={["A","B"]}。

当使用可多选的select时,select组件的值在选项被选择时不会更新,只有选项的selected属性会发生变化。你可以使用ref或者syntheticEvent.target来访问选项,检查他们是否被选中。

下面的例子中,handleChange循环检查DOM,并过滤出哪些选项被选中了。

class@H_502_12@ Hello@H_502_12@ extends@H_502_12@ React@H_502_12@.Component@H_502_12@ {@H_502_12@
    constructor(props) {
        super@H_502_12@(props);
        this@H_502_12@.state = {
            option@H_502_12@: ["B"@H_502_12@]
        };
    }
 handleChange@H_502_12@ = (event)@H_502_12@ =>@H_502_12@ {
        var@H_502_12@ checked = [];
        var@H_502_12@ sel = event.target;
        for@H_502_12@ (var@H_502_12@ i = 0@H_502_12@; i < sel.length; i++){
            var@H_502_12@ option = sel.options[i];
            if@H_502_12@ (option.selected){
                checked.push(option.value);
            }
        }
        this@H_502_12@.setState({
            option@H_502_12@: checked
        });
    }
 submitHandler@H_502_12@ = (event)@H_502_12@ =>@H_502_12@ {
        event.preventDefault();
        alert(this@H_502_12@.state.options);
    }
    render () {
        return@H_502_12@(
            <form onSubmit={this@H_502_12@.submitHandler}>
                <select multiple="true"@H_502_12@ value={this@H_502_12@.state.options}
                onChange={this@H_502_12@.handleChange}>
                    <option value="A"@H_502_12@>1@H_502_12@</option>
                    <option value="B"@H_502_12@>2@H_502_12@</option>
                    <option value="C"@H_502_12@>3@H_502_12@</option>
                </select>
                <br />
                <button type="submit"@H_502_12@>speak</button>
            </form>
        );
    }
}

复选框和单选框

复选框和单选框使用的则是完全不同的控制方式。

在HTML中,类似为checkBox或者radio<input/>的行为完全不一样,通常,复选框或者单选框的值是不变的,只有checked的状态会变化,要控制复选框或者单选框,就要控制他们的checked属性,你要可以在非约束的复选框或者单选框中使用defaultChecked。

//非约束的@H_502_12@
var@H_502_12@ MyForm = React.createClass({
    submitHandler: function(event@H_502_12@){
        event@H_502_12@.preventDefault();
        alert(this@H_502_12@.refs.checked@H_502_12@.getDOMNode().checked@H_502_12@);
    },render: function(){
        return@H_502_12@ (
            <form onSubmit={this@H_502_12@.submitHandler}>
                <input ref@H_502_12@="checked"@H_502_12@ type="checkBox"@H_502_12@ value@H_502_12@="A"@H_502_12@ defaultChecked="true"@H_502_12@ />
                <br />
                <button type="submit"@H_502_12@>speak</button>
            </form>
        );
    }
});

//约束的@H_502_12@
var@H_502_12@ MyForm = React.createClass({
    getInitialState: function(){
        return@H_502_12@ {
            checked@H_502_12@: true@H_502_12@
        };
    },handleChange: function(event@H_502_12@){
        this@H_502_12@.setState({
            checked@H_502_12@: event@H_502_12@.target.checked@H_502_12@
        });
    },submitHandler: function(event@H_502_12@){
        event@H_502_12@.preventDefault();
        alert(this@H_502_12@.state.checked@H_502_12@);
    },render: function(){
        return@H_502_12@ (
            <form onSubmit={this@H_502_12@.submitHandler}>
                <input type="A"@H_502_12@ checked@H_502_12@={this@H_502_12@.state.checked@H_502_12@} onChange={this@H_502_12@.handleChange} />
                <br/>
                <button type="submit"@H_502_12@>speak</button>
            </form>
        );
    }
});

在这两个例子中,<input/>的值一直都是A,只有checked的状态在变化。

表单元素的name属性

在React中,name属性对于表单元素来说并没有那么重要。因为约束表单组件已经把值存储到了state中,并且表单的提交事件也会被拦截。在获取表单值的时候,name属性并不是必需的。对于非约束的表单组件来说,也可以使用refs来直接访问表单元素。虽然如此,name仍然是表单组件中非常重要的一部分。

  • name属性可以让第三方表单序列化类库在React中正常工作。
  • 对于任然使用传统提交方式的表单来说,name属性是必需的。
  • 用户的浏览器中,name被用在自动填写常用信息中,比如用户地址等。
  • 对于非约束的单选框组件来讲,name是有必要得,它可作为这些组件分组的依据。确保在同一时刻,同一表单中拥有同样name的单选框只有一个可以被选中。如果不使用name属性,这一行为可以使用约束的单选框实现。

多表单与change处理器

在使用约束的表单组件时,没有愿意重复地为每一个组件编写change处理器。可以在React中重用一个事件处理器。

可以有两种方式:通过.bind传递其他参数;使用DOMNode的name属性来判断需要更新哪个组件的状态。

示例可以看page75~77

除此之外,React还在addon中提供了一个mixin,React.addons.LinkedStateMixin,通过另一种方式解决同样的问题。

React.addons.LinkedStateMixin为组件提供了一个linkState方法。linkState返回一个对象,包含value和requestChange两个属性

value根据提供的name属性从state中获取对应的值。

requestChange是一个函数,使用心得值更新同名的state。

mixins@H_502_12@:[React.addons.LinkedStateMixin]
 submitHandler@H_502_12@ = (event)@H_502_12@ =>@H_502_12@ {
    event.preventDefault();
    alert(this@H_502_12@.state.family_name);
}

<input type="text"@H_502_12@ name="family_name"@H_502_12@ valueLink={this@H_502_12@.linkState('family_name'@H_502_12@)} />

这种方法便于控制表单域,把其值保存在福组件的state中。而且,其数据流仍然与其他约束的表单元素保持一致。

但是,使用这种方式往数据流中添加定制功能时,复杂度会增加。我们建议只在特性的场景下使用。因为传统的约束表单组件提供了同样的功能而且更加灵活。

自定义表单组件

当编写自定义组件时,接口应当与其他表单组件保持一致。这可以帮助用户理解代码,明白如何使用自定义组件,且无须深入到组件的实现细节里。

示例:page79~82

Focus

React实现了autoFocus属性,因此在组件第一次被挂载时,如果没有其他的表单聚焦时React就会把焦点放到这个组件对应的表单域中,例如:

<input type@H_502_12@="given_name"@H_502_12@autoFocus="true"@H_502_12@ />

还有一种方法就是调用DOMNode的focus方法,手动设置表单域聚焦。

可用性

React虽然提高了开发者的生产力,但是也有不尽如人意的地方,使用React编写的组件常常缺乏可用性,例如表单提交无法通过键盘敲击回车键来实现,而这明明是HTML表单默认的提交方式。

要编写具有高可用性的好组件其实也不难,只是编写组件时需要花时间进行更多的思考。

  • 把要求传达清楚
  • 不断地反馈
  • 迅速响应
  • 符合用户的预期
  • 可访问
  • 减少用户的输入

猜你在找的React相关文章