阅读 239

React自定义组件应用(父子之间传递数据)

React自定义组件应用

今天在学习React自定义组件的时候就联想到了之前在学小程序的时候写的自定义组件,不过它们子向父传递数据和父向子传递数据的方式是有所不同的。

组件化编码流程

这里通过一个案例来演示。

  1. 拆分组件: 拆分界面,抽取组件
  2. 实现静态组件: 使用组件实现静态页面效果
  3. 实现动态组件:动态显示初始化数据(数据类型、数据名称)
  4. 交互(绑定事件监听等)

比如实现下面这个todos,因为这里主要是要讲组件,所以对这些样式什么的就不做详细的解释了。

todos.png

将这一整个看成App组件,里面分成4个小组件,分别为HeaderListItemFooter。下面通过这个案例来说一下子向父传递数据父向子传递数据的方法。

todos zujian.png

1. 父向子传递数据

动态渲染List

首先,Item 是 List 的子组件,在动态渲染的过程中,要用一个 List 向 Item 传递列表的值让 Item 渲染出来,此时我们没办法直接让列表的数据直接从List传递到Item,因此应该把此时的状态state中的数据todos定义在App组件中,通过App组件传给App组件的子组件List,再由List将值传递给Item从而将todos渲染出来。子组件再从this.props取出从父组件传过来的值。

简单讲,这里的涉及到的知识点就是父向子传递数据。

// App.jsx
export default class App extends Component {
    state = {
        todos: [
            { id: '1', name: '吃饭', done: true },
            { id: '2', name: '睡觉', done: false },
            { id: '3', name: '打代码', done: false },
        ]
    }
    render() {
        const { todos } = this.state;
        return (
            <div className="todo-container">
                <div className="todo-wrap">
                    <Header></Header>
                    <List todos={todos}></List>
                    <Footer></Footer>
                </div>
            </div>
        )
    }
}
复制代码

之前学习小程序的时候,也有这个知识点(微信小程序——自定义组件),不过React中的子向父传递数据中,我们是要对props进行类型限制,在小程序中,还需要子组件在json文件中的properties中定义从父组件传递的数据。

注意点:

  • 表示是否完成的checkboxchecked属性值应为defalutChecked,否则checked值无法通过点击改变
  • 在渲染todos要给每一个Item添加一个key值(key={todos.id})

2. 子向父传递数据

input添加todos

Header要将用户输入的值传递给List需要经过这个数据传递的过程:Header -> App -> List;

也就是说,这个的传递数据方式与上面的动态渲染相比,多了一个子向父传递数据。这个的实现方式是通过props从父组件App给子组件List传递一个函数(addTodos)。也就是说,在React中,子向父传递数据是通过函数来建立关系的。

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

接着,在子组件(Header)中调用这个函数,当键盘按回车键的时候调用这个函数,然后把用户输入的东西给父组件中定义的函数。

handleKeyUp = (e) => {
    const { keyCode, target } = e;
    if (keyCode !== 13) return;
    if (target.value.trim() === '') return;
    const todoObj = { id: nanoid(), name: target.value, done: false }
    this.props.addTodos(todoObj)
    target.value = '';
}
复制代码

有一个库(uuid)能够获取唯一标识,给id赋值,让每一个item都有一个独一无二的id值作为key,进行遍历。在终端输入npm install uuid或者npm add nanoid都可以下载这个库,前者的文件比较大,建议下载第二个。在要调用的时候记得在引入import {nanoid} from 'nanoid'

对props进行限制

props传递的属性类型进行必要性的限制。设置了类型之后,如果在传的值不是这个类型的话,就会报错

引入prop-types库:在终端输入npm add prop-types。 引入import PropTypes from 'prop-types'

static propTypes {
    addTodos: PropTypes.func.isRequired
}
复制代码

总结

  1. 拆分组件、实现静态组件。注意:classNamestyle的写法

  2. 动态初始化列表,如果是在某个组件使用就将state放在自身,如果是在多个组件使用就放在父组件中(状态提升)

  3. 【父组件】给【子组件】传递数据:通过props传递

    【子组件】给【父组件】传递数据:通过props传递,要求父提前给子一个函数

  4. 注意defaultCheckedchecked的区别。类似的还有:defaultValuevalue

  5. 状态改变记得setState

文章分类
前端
文章标签