reactjs前端实践|第三篇:TodoList示例事件、state、props、refs

实践三

Todo List示例,未使用redux。内容涉及到展示组件与容器组件的合理使用,事件处理,参数传递,控件访问,组件功能设计等方面。其中遇到的坎,设置输入焦点,由于使用了styled-components而有不同;每个组件应试包含哪些state,是否应该进行状态提升;子组件如何向父组件传递数据。

代码分析

组件拆分:Li单个信息条目、LiList信息条目列表、InputAndButton输入组件、App容器组件。App的State包含一个item数组,存放信息列表;InputAndButton的State包含一个inputValue变量,存入用户本次输入的信息。其它组件不含State,为展示组件。

展示组件

Li.js,展示一条信息,数据来自父组件

const Li = (props) => {
    return (                           
        <TodoLi>{props.text}</TodoLi>              //此处不能加key(但父组件要向它传递),否则会有警告
    );
};
export default Li;

LiList.js,展示信息列表,因为输入组件也会修改数据,所以state提升到容器组件中。

const LiList = (props)=>{
    return (
        <TodoUl>
            {props.items.map((item)=>{             //map方法来完成列表构建
                return <Li {...item}></Li>;        //item中要包含一个key字段,否则会有警告
            })}
        </TodoUl>
    );
};
export default LiList;

输入组件

输入组件自己控制输入框的数据显示及清除,开始我把一切事件处理全放到App中了,这样方便了数据传递,但破坏了输入组件的内聚性。正确的方式是:输入组件自己控制界面的显示,只有在回车键按下或鼠标点击add按钮时,才将输入框中的数据传递给父组件(App)。

InputAndButton.js

class InputAndButton extends Component {
    constructor(props)    {
        super(props);
        this.state={
            inputValue:''                      //用来处理鼠标点击时取得输入数据
        };
    }
    onChange = e => {
        this.setState({
            inputValue:e.target.value         //按键时保存输入数据
        })
    };
    addItem = e => {
        if(e.which === 13 || e.type === 'click'){    //回车或鼠标点击
            if(this.state.inputValue.trim().length > 0) {     //输入不为空
                this.props.onSave(this.state.inputValue.trim());   //调用父组件提供的函数,向父组件传递数据。
                e.target.value = '';     //清空输入
                this.setState({          
                    inputValue:''
                })
            }
        }
    };
    render = () => {
        return (
            <div>
                <TodoInput onChange={this.onChange}
                           onKeyUp={this.addItem}
                           placeholder="enter task"
                           value={this.state.inputValue}>
                </TodoInput>
                <TodoButton onClick={this.addItem} type="submit">add</TodoButton>
            </div>
        );
    }
}
export default InputAndButton;

容器组件

class App extends Component {
    constructor(props){
        super(props);
        this.state={
            items:[]                   //信息列表数据
        };
    }
    handleSave(text){                 //传递到子组件的函数,接收数据并追加条目
        if(text.length !== 0){
            this.state.items.push({key: new Date().getTime(),text});     //key设定唯一值,不作说明,网上资料很多
            this.setState({
                items: this.state.items,})
        }
    };
    render() {
        return (
            <div>
                <InputAndButton onSave={this.handleSave.bind(this)}/>                     //处理函数以props传给子组件
                <LiList items={this.state.items}/>
            </div>
        );
    };
}
export default App;

输入焦点控制

利用特殊的属性 Ref来访问子组件中的控件,并控制输入焦点,需要注意的是:styled-components对这个属性有些改变,要用innerRef来替代ref,不然拿到的是一个 StyledComponent包装的对象,而不是DOM结点。有疑问,去看其文档的Tips and tricks部分之Refs to DOM nodes。

App.js中输入组件修改如下:

<InputAndButton ref={comp => { this.InputComponent = comp; }} onSave={this.handleSave.bind(this)}/>

App.js中增加componentDidMount处理,在组件加载完成时设置输入焦点。

componentDidMount (){
        this.InputComponent.focus();
    };

InputAndButton.js中修改input如下:

<TodoInput innerRef={el=> { this.el = el; }}   ...

InputAndButton.js中增加函数,供父组件中调用。

focus = () => {
        this.el.focus();
    };

项目地址

https://git.oschina.net/zhoutk/reactodo.git
https://github.com/zhoutk/reactodo.git

使用方法

git clone https://git.oschina.net/zhoutk/reactodo.git
or git clone https://github.com/zhoutk/reactodo.git
cd reactodo
npm i
git checkout todo_list_react
npm start

小结

这次实践,学会了事件,数据传递,组件划分,功能设计等基本方法,可以去折腾redux了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom