本文共 5468 字,大约阅读时间需要 18 分钟。
所谓组件,即封装起来的具有独立功能的UI部件,用来组合成更高级东西的物件,通俗来说,就是创建一个元素,组件有以下规范:
- 组件名必须大写开头
- 只能包含一个顶层标签
1、函数组件(无状态组件、UI 组件)
是一个纯函数,只用组件展示,组件只负责根据外部传入的 props 来展示,书写更简洁,执行效率更高(推荐)
import React from 'react'// 函数组件function App(){ returnwelcome fqniu}export default App
2、类组件(状态组件、容器组件)
类组件有更丰富的特性,如:state 状态、生命周期、this 等
import React from 'react'// 类组件class Todolist extends React.Component{ render(){ return (Todolist) }}export default Todolist
这里需要使用类组件,因为修改数据后,需要更新视图
import React from 'react'class Todolist extends React.Component { constructor() { // 执行父类后才能继承父类属性,之后才能使用this super() // 给当前组件添加状态 this.state = { keyword:'', title:'todolist待办事项', datalist:[ { id: 1, target: '按时吃饭', done: false, addtime: Date.now() }, { id: 2, target: '早睡早起', done: false, addtime: Date.now() } ] } // 改变自定义方法this指向 this.add = this.add.bind(this) this.changeKeyword = this.changeKeyword.bind(this) this.removeItem=this.removeItem.bind(this) this.completeItem=this.completeItem.bind(this) } // 添加自定义方法:默认没有this执行 add(){ const { datalist,keyword} = this.state console.log(datalist) const newData = { id: datalist.length + 1, target: keyword, done: false, addtime: Date.now() } // this.todolistData.unshift(data) this.setState({ datalist:[newData,...datalist], keyword:'' }) // 清除并自动获得焦点 this.keyword.focus() } // 完成 completeItem(id){ const datalist = this.state.datalist.map(item=>{ if(item.id === id){ item.done=true } return item }) console.log('datalist=', datalist) this.setState({ datalist }) } // 移除 removeItem(id){ this.setState({ datalist:this.state.datalist.filter(item=> item.id !== id) }) } // 事件 e changeKeyword(e){ this.setState({ keyword:e.target.value }) } render() { // 解构 const { datalist,title,keyword} = this.state return () }}export default Todolist{ title}
this.keyword=el}/>
{ datalist.map((item,idx)=>{ return ( 序号 待办事项 是否完成 操作 { /* {添加时间 } */}) }) } { idx+1} { item.target} { item.done ?'是':'否'} 总数:{ datalist.length}, 完成:{ datalist.filter(item=>item.done).length}, 未完成:{ datalist.filter(item=>!item.done).length}
解析其中的部分代码:
1、
2、添加的super()
执行父类后才能继承父类属性,之后才能使用this ,这里官网也有讲解。。。自定义方法:默认是没有this指向的
,需要单独改变this指向; 3、修改状态只能用 this.setState()
,规则:创建新的数据并覆盖; 4、event参数
一直存在,事件处理函数最后一个参数; 5、refs
: ref 属性用在html元素上,得到元素节点;ref属性用在组件上,得到组件实例; 6、bind
: bind改变函数this指向只在第一次生效 ,其中使用地方this.removeItem.bind(this,item.id)
;
- bind 调用的时候,不会执行 这个函数,而是返回一个新的函数
- 这个新的函数就是一个改变了 this 指向以后的 函数
注意点:
map,filter
但是不能用 forEach
因为forEach 没有return 返回值;{}
;websocket技术
;this.setState()
,不同于Vue的getter&setter
,注意:直接修改state数据无法刷新页面;v-model
指令,可以很方便的实现 数据的双向绑定
; 但是,在 React 中,默认只是单向数据流
,也就是 只能把 state 上的数据绑定到 页面,无法把 页面中数据的变化,自动同步回 state ; 如果需要把 页面上数据的变化,保存到 state,则需要程序员手动监听onChange
事件,拿到最新的数据,手动调用this.setState({ })
更改回去;onClick={this.removeItem.bind(this,item.id)}
这里不能写成 onClick={this.removeItem(item.id)}
因为执行时会立即调用,不用点击就触发了函数调用,比如 fn()调用函数
,所以这里使用 bind 因为bind 返回一个函数。render方法里面有默认的this指向
,而自定义方法没有,需要改变this指向;call和apply改变后会先执行调用一次改变this后的函数
;多次对一个函数使用bind 改变this指向 不影响
,因为 bind只会在第一次改变,后期改不了;初始化时,先对自定义方法使用bind 改变this指向
;bind(target,...args)
, 只在第一次生效;什么时候用到re?
:当需要用到节点时,比如音频视频等 用 ref 获取节点1、数据绑定
列表循环
3、事件绑定
bind(target,...args)
, 只在第一次生效;4、refs
// 字符串 // 获取:this.refs.xxx(不推荐) < input ref="xxx"> // 回调函数(推荐) const callback = function(el){ this.keyword = el } < input ref={ callback} /> // React.createRef() // 获取:myref.current const myref = React.createRef() < input ref={ myref} />
1、受控组件
:把state绑定到表单元素的value属性,并绑定onChange事件;
非受控组件
:表单元素不受state / props控制,通过节点方式获取; 组件的状态
this.state.xxx
this.setState()
原则:创建新的数据并覆盖组件通讯:
1、父子通讯:props;
父组件操作:定义属性并传递数据
子组件操作:函数组件:函数的第一个参数、类组件:this.props
2、子父通讯:把父组件的方法传到子组件去执行并传递参数;
父组件操作:定义方法并通过props传入子组件 (数据在哪里就把方法定义在哪里)
子组件操作:执行方法并传递参数
3、兄弟通讯:状态提升
把状态放到兄弟组件的共同的父级
4、多层次组件通讯;
逐层传递
:一层一层传递(比较繁琐)Context
1、创建Context ;
2、父组件操作:Provider 共享数据 其中的 value;
3、子组件操作:接收数据 ;分为函数组件 :Consumer / 类组件 : Consumer 和 this.context
转载地址:http://nnomz.baihongyu.com/