功能界面的组件化编码流程

我们在项目中需要写一些功能页面的时候,也就是添加新的功能组件,比如我们想要创建一个增删改查表单案例,用react去写,我们就需要按照步骤来。

1.拆分组件,抽取组件。2.实现静态组件,使用组件实现静态页面效果 。3.实现动态组件,动态显示初始化数据,以及页面交互。

说起来很笼统,我们之间上案例,

​​​​​​​

这个是一个表单功能,我们直观的看呢,拆分组件,首先外壳App组件就是大盒子,然后里面的就是我们需要的自定义组件了,我们分为3个组件,首先是输入框,然后是列表,以及尾部。很明显我们的组件对应的就是 Header ,List,Footer。但是呢我们在创建组件的时候,不仅仅要考虑样式的复现,更重要的是动态数据的流动,也就是所谓的数据传输。比如这里呢,列表需要接收数据然后复现每一行的内容,那么每一行的内容我们就需要用Item组件去渲染。

首先html css 我们之间跳过,现在我们的页面是

现在我们第一步就是显示出Item组件的内容,也就是xxxx这里我们是没有数据的。我们现在用的类组件,

复制代码
export default class App extends Component {
    state ={
        todos:[
            {id:"001",name:'吃饭',done:true},
            {id:"002",name:'睡觉',done:true},
            {id:"003",name:'写代码',done:false}
        ]
    }

 render() {
        const {todos} = this.state
        return (
            <div className="todo-container">
                <div className="todo-wrap">
                    <Header addTodo={this.addTodo}/>
                    <List todos={todos} updataTodo={this.updataTodo}/>
                    <Footer/>
                </div>
            </div>
        )
    }


}

在App组件中呢,我们首先定义我们的state是一个对象,然后里面第一个属性是todos数组对象,里面存放我们想要展示的数据,然后呢我们想要Item组件去渲染出来,我们这时候就要传数据给Item,但是App和Item是祖孙关系,中间隔了一代,这就有点尴尬了,也就是一层一层的传。

首先我们之间todos={todos},把我们的数据给List,然后呢List的props就接收到了todos对象,也就是this.props.todos就是我们传过去的内容,我们上代码。

复制代码
export default class List extends Component {
    render() {
        const {todos,updataTodo} = this.props
        return (
            <ul className="todo-main">
            {
                 todos.map((todo)=>{
                 return <Item key={todo.id} {...todo} updataTodo={updataTodo}/>
             })
            }

            </ul>
        )
    }
}

拿到了数据,我们就需要传数据给Item组件了,首先用key={todo.id}这是给每一个Item的组件定key值方便以后拿取,或者说这是必要的。然后我们传的数据是{...todo},也就是我们每遍历一次,就传新的当前的数组对象里面的对应index的对象给Item,那么我们祖孙就传输完毕了,看Item的代码

复制代码
export default class Item extends Component {
    state = {mouse:false}//鼠标移入移出
    handleMouse = (flag)=>{
        return()=>{
            this.setState({mouse:flag})
        }
    }
    //勾选或者取消一个回调
    handleCheck =(id)=>{
        return(event)=>{
            console.log(id,event.target.checked);
            this.props.updataTodo(id,event.target.checked)
        }
    }
        render() {
            const {id,name,done} = this.props
            const {mouse} = this.state
        return (
            <li style={{backgroundColor:mouse? '#ddd':'white'}} onMouseEnter={this.handleMouse(true)} onMouseLeave={this.handleMouse(false)} >
                <label>
                    <input type="checkbox" defaultChecked={done} onChange={this.handleCheck(id)}/>
                    <span>{name}</span>
                </label>
                <button className="btn btn-danger" style={{display:mouse? 'block':'none'}}>删除</button>
            </li>
        )
    }
}

我们Item组件解构赋值拿取到了我们List组件传过来的依旧是props,然后我们之间{name}就是我们所谓的事情,然后{done}就是我们事情的状态,通过true以及false来判断是否做过。

这时候我们的网页就变成了

​​​​​​​

这个样子。然后我们就完善我们第一个组件Header,这时候我们发现,如果我们通过敲回车的话给List组件添加新的state,也就是改变了App组件里面的state,子给父传,我们想不到办法以现在的知识量,然后我们发现可以通过函数的回调,会有返回值,通过这个来让子组件给父组件传输数据,也就是更改父组件里面state。

复制代码
export default class Item extends Component {
    state = {mouse:false}//鼠标移入移出
    handleMouse = (flag)=>{
        return()=>{
            this.setState({mouse:flag})
        }
    }
    //勾选或者取消一个回调
    handleCheck =(id)=>{
        return(event)=>{
            console.log(id,event.target.checked);
            this.props.updataTodo(id,event.target.checked)
        }
    }
        render() {
            const {id,name,done} = this.props
            const {mouse} = this.state
        return (
            <li style={{backgroundColor:mouse? '#ddd':'white'}} onMouseEnter={this.handleMouse(true)} onMouseLeave={this.handleMouse(false)} >
                <label>
                    <input type="checkbox" defaultChecked={done} onChange={this.handleCheck(id)}/>
                    <span>{name}</span>
                </label>
                <button className="btn btn-danger" style={{display:mouse? 'block':'none'}}>删除</button>
            </li>
        )
    }
}

import React, { Component } from 'react'
import {nanoid} from 'nanoid'
import './index.css'

export default class Header extends Component {
 handleKeyUp=(event)=>{
    //结构赋值获取
    const {keyCode,target} = event
    if(keyCode!==13) return
    //判断是否会车键位
    console.log(target.valye,keyCode);
    if(target.value.trim()===''){
        alert("error")
        return
    }
    //准备好一个todo对象
    const todoObj={id:{nanoid},name:target.value,done:false}
    this.props.addTodo(todoObj)
 }
    
    render() {
        return (
            <div className="todo-header">
                <input onKeyUp={this.handleKeyUp} type="text" placeholder="请输入你的任务名称,按回车键确认"/>
                {/* onkeyup是按键松开事件,前面的keycode指的是键位,回车键是13 */}
            </div>
        )
    }
}

我们代码在这里。首先我们给Header传一个函数,addTodo={this.addTodo},然后函数里面是

复制代码
addTodo = (TodoObj)=>{
        const {todos} = this.state
        const newTodos = [TodoObj,...todos]
        this.setState({todos:newTodos})
    }

通过返回的参数,我们之间添加在state的最上面,也就是在上面添加对象,然后更新state实现这个效果。我们再来看Header组件是怎么实现的。首先给输入框添加按压事件,onKeyUp={this.handleKeyUp},然后我们就可以去函数里面操作了。

首先我们是通过回车来添加state的,说明当我们输入文本按回车的时候,函数才会执行。首先我们通过keyCode以及target.value = event来获取当前事件发生的按键以及对应的文本,然后判断keyCode==13才继续执行,记住了还要target.value.trim()===''也要满足,也就是不能为空包含不能有空格。trim()去掉空格。然后我们就可以调用函数,首先定义todoObj={id:{nanoid},name:target.value,done:false},这里的nanoid是一个库,引入后我们可以之间调用nanoid方法随机生成id,防止id重复。然后直接this.props.addTodo(todoObj)直接使用函数并且传回去数据,这样我们就可以实现效果了。

​​​​​​​​​​​​​​

相关推荐
空中海9 分钟前
01 React Native 基础、核心组件与布局体系
javascript·react native·react.js
空中海22 分钟前
05 React架构设计、项目实践与专家清单
前端·react.js·前端框架
空中海3 小时前
04 工程化、质量体系与 React 生态
前端·ubuntu·react.js
空中海3 小时前
03 性能、动画与 React Native 新架构
react native·react.js·架构
空中海5 小时前
02 React Native状态、导航、数据流与设备能力
javascript·react native·react.js
空中海6 小时前
04 React Native工程化、质量、发布与生态选型
javascript·react native·react.js
郑生zs8 小时前
Hooks-useEffect
react.js
光影少年8 小时前
react函数组件、类组件、纯组件、受控/非受控组件
前端·react.js·掘金·金石计划
空中海9 小时前
05 React Native架构设计、主线项目与专家实践
javascript·react native·react.js
killerbasd19 小时前
还是迷茫 5.3
前端·react.js·前端框架