react->Context笔记

此文章想记录一下react的context的使用以便于以后的复习

先附上我的目录

 

第一步在context.js上写下这样的代码:

context.js

import React from 'react'
const MyContext = React.createContext( 'defalut' )
export default MyContext

第二步在TodoList.js里把context.js引进来,然后再把要传给子组件用的方法和数据赋值到context.js上

TodoList.js

  1 import React, { Component } from 'react'
  2 import TodoForm from './TodoForm'
  3 import TodoContent from './TodoContent'
  4 import MyContext from '../context' // 把context.js引进来
  5 class TodoList extends Component {
  6     constructor () {
  7         super ()
  8         this.state = {
  9             checkedAll:false,
 10             datalist: [
 11                 {
 12                     id: Date.now(),
 13                     title: "明年实现月薪过万",
 14                     done: false,
 15                     selected: false
 16                 },
 17                 {
 18                     id: Date.now() + 10,
 19                     title: "男同学变成高富帅,迎娶白富美",
 20                     done: false,
 21                     selected: false
 22                 },
 23                 {
 24                     id: Date.now() + 20,
 25                     title: "女同学变成白富美,迎娶高富帅",
 26                     done: false,
 27                     selected: false
 28                 }
 29             ]
 30         }
 31         this.addItem = this.addItem.bind( this )
 32         this.removeItem = this.removeItem.bind( this )
 33         this.completeItem = this.completeItem.bind( this )
 34         this.selecteItem = this.selecteItem.bind( this )
 35         this.selectedAll = this.selectedAll.bind( this )
 36         
 37     }
 38     addItem ( title ) { // 添加事项
 39         let datalist = this.state.datalist
 40         datalist.unshift(
 41             {
 42                 id: Date.now() + 20,
 43                 title,
 44                 done: false,
 45                 selected: false
 46             }
 47         )
 48         this.setState({ datalist })
 49     }
 50     removeItem ( id ) { // 删除事项
 51     //    let datalist = this.state.datalist.filter( item => item.id !== id )
 52        this.setState({ datalist: this.state.datalist.filter( item => item.id !== id ) })
 53     }
 54     completeItem ( id ) { // 变成完成事项
 55         let datalist = this.state.datalist.map( item => {
 56             if ( item.id === id ) {
 57                 item.done = !item.done
 58             }
 59             return item
 60         })
 61         this.setState( { datalist } )
 62     }
 63     selecteItem ( id ) {  // 改变check状态
 64        let datalist = this.state.datalist.map( item => {
 65            if ( item.id === id ) {
 66                item.selected = !item.selected
 67            }
 68            return item
 69        })
 70        this.setState( { datalist, checkedAll: datalist.every( item => item.selected ) } )
 71     }  
 72     selectedAll () {      // 全选
 73         let checkedAll = !this.state.checkedAll
 74         let datalist = this.state.datalist.map( item => {
 75             item.selected = checkedAll
 76             return item
 77         })
 78         this.setState( { checkedAll,datalist } )
 79     }
 80     render () {
 81         let {selecteItem,removeItem,completeItem,addItem} = this
 82         let { datalist, checkedAll } = this.state
 83         return (
 84             <div>
 85                <MyContext.Provider value = { { selecteItem,removeItem,completeItem,addItem } }>  // 将需要的方法传到MyContext里传递,那么就不用一个个传递到子组件这么麻烦了,但是使用context会使组件复用性变差
 86                     <TodoForm 
 87                     addItem = { addItem }
 88                     ></TodoForm>
 89                     <TodoContent
 90                     selectedAll = { this.selectedAll }
 91                     datalist = { datalist }
 92                     checkedAll = { checkedAll }
 93                     >
 94                     </TodoContent>
 95                 </MyContext.Provider>
 96                 
 97             </div>
 98         )
 99     }
100 }
101 export default TodoList

TodoList的子组件有TodoContent.js和TodoForm.js

TodoContent.js

 1 import React from 'react'
 2 import PropTypes from 'prop-types'
 3 import TodoItem from './TodoItem'
 4 function TodoContent ( props ) {
 5     console.log( 'TodoContent.props', props )
 6     return (
 7         <>
 8             <table>
 9                 <thead>
10                     <tr>
11                         <th><input type = 'checkbox' checked = { props.checkedAll } onChange = { props.selectedAll } />全选</th>
12                         <th>#</th>
13                         <th>待办事项</th>
14                         <th>是否完成</th>
15                         <th>操作</th>
16                     </tr>
17                 </thead>
18                 <tbody>
19                     {
20                         props.datalist.map( (item,idx) => {
21                             return (
22                                 <TodoItem
23                                 key = { item.id }
24                                 data = { item }
25                                 idx = { idx }
26                                 >
27                                 </TodoItem>
28                             )
29                         } )
30                     }
31                 </tbody>
32             </table>
33             <div>总数:{props.datalist.length},完成:{props.datalist.filter( item => item.done).length},未完成:{props.datalist.filter( item => !item.done).length}</div>
34         </>
35     )
36 }
37 TodoContent.propTypes = {
38     datalist: PropTypes.array.isRequired
39 }
40 TodoContent.defaultProps = {
41     datalist: []
42 }
43 export default TodoContent

TodoItem.js(TodoContent.js的子组件)

 1 import React from 'react'
 2 import MyContext from '../context'
 3 import Button from './TodoButton'
 4 function TodoItem({ data, idx }) {
 5     return (
 6         <MyContext.Consumer> // 使用此标签来把context的值传进来,那么函数组件就可以使用这样的方式来接受context父组件传过来的方法了,相当于vue的bus总线一样,只不过react的写法多端
 7             {
 8                 value => {
 9                     let { selecteItem,removeItem,completeItem } = value
10                     return (
11                         <tr>
12                             <td>
13                                 <input type='checkbox' checked={data.selected} onChange={selecteItem.bind(null, data.id)} />
14                             </td>
15                             <td>{idx + 1}</td>
16                             <td>{data.title}</td>
17                             <td>{data.done ? '是' : '否'}</td>
18                             <td>
19                                 <Button onClick={completeItem.bind(null, data.id)}>完成</Button>
20                                 <Button onClick={removeItem.bind(null, data.id)}>删除</Button>
21                             </td>
22                         </tr>
23                         )
24                     }
25                 }
26         </MyContext.Consumer>
27     )
28 }
29 export default TodoItem

TodoButton.js(TodoItem.js的子组件)

 能够获取到父组件传进来的文字和事件,

 1 import React from 'react'
 2 const TodoButton = props => {
 3     // console.log('Button:',props.children,React.Children, 'props->',props,'React->',React);
 4     React.Children.forEach(props.children,function(item,idx){
 5         // console.log(item,idx,'BUTTON出来的')
 6     })
 7     return (
 8         <button onClick = { props.onClick }>{ props.children }</button>
 9     )
10 }
11 export default TodoButton

TodoForm.js(TodoList的子组件)

TodoForm.js是类组件,有自己的状态也有this,所以可以这么写,通过TodoForm.contextType = MyContext,就能在类组件使用this.context.xxx()使用context的方法了

 1 import React, { Component } from 'react'
 2 import MyContext from '../context'
 3 export default class TodoForm extends Component {
 4     constructor(props) {
 5         super(props)
 6         this.state = {
 7             title: ''
 8         }
 9         this.changeTitle = this.changeTitle.bind( this )
10         this.additem = this.additem.bind( this )
11         this.enter = this.enter.bind( this )
12     }
13     changeTitle(event) {
14         this.setState({ title: event.target.value })
15     }
16     additem() {
17         let  title  = this.state.title
18         if ( String( title ).trim() === "" ) {
19             alert( '事项名称必填!' )
20             return
21         }
22         this.context.addItem( title )
23         console.log('title->', title)
24         this.setState({ title: '' })
25         this.eles.focus()
26     }
27     enter(event) {
28         if (event.which === 13) {
29             this.additem()
30         }
31     }
32     render() {
33         return (
34             <div>
35                 <input
36                     type='text'
37                     ref = { ele => this.eles = ele}
38                     value = { this.state.title }
39                     onChange = { this.changeTitle }
40                     onKeyPress = { this.enter }
41                 />
42                 <button onClick={this.additem}>添加</button>
43             </div>
44         )
45     }
46 }
47 TodoForm.contextType = MyContext

函数组件和类组件有所区别

因为class组件有this,所以可以使用this.context,而this.context是react里面自带,可以来获取context的值

但是函数组件没有this,只能使用Consumer来获取context的值,但是Consumer是class类组件和函数组件都能用的

所以使用context的方式也有所区别。

如果我哪里不对,希望大家纠正

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-07-25 23:24  强者之途  阅读(122)  评论(0编辑  收藏  举报
/* 看板娘 */