博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于react的todolist实现(1)
阅读量:660 次
发布时间:2019-03-15

本文共 5468 字,大约阅读时间需要 18 分钟。

基于react的todolist实现

基于react的todolist实现

组件是什么?

所谓组件,即封装起来的具有独立功能的UI部件,用来组合成更高级东西的物件,通俗来说,就是创建一个元素,组件有以下规范:

  • 组件名必须大写开头
  • 只能包含一个顶层标签

1、函数组件(无状态组件、UI 组件)

是一个纯函数,只用组件展示,组件只负责根据外部传入的 props 来展示,书写更简洁,执行效率更高(推荐)

import React from 'react'// 函数组件function App(){
return
welcome 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 (

{
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}
) }}export default Todolist

解析其中的部分代码:

1、 super() 执行父类后才能继承父类属性,之后才能使用this ,这里官网也有讲解。。。

2、添加的自定义方法:默认是没有this指向的,需要单独改变this指向;
3、修改状态只能用 this.setState(),规则:创建新的数据并覆盖;
4、event参数 一直存在,事件处理函数最后一个参数;
5、refs: ref 属性用在html元素上,得到元素节点;ref属性用在组件上,得到组件实例;
6、bind: bind改变函数this指向只在第一次生效 ,其中使用地方 this.removeItem.bind(this,item.id)

  • bind 调用的时候,不会执行 这个函数,而是返回一个新的函数
  • 这个新的函数就是一个改变了 this 指向以后的 函数

注意点:

  1. 数组可以直接显示在结构上,但是里面是对象形式的不行,例如:[ {},{},{} ] ,而对象也不能直接显示在结构上;
  2. 可以 用map,filter但是不能用 forEach因为forEach 没有return 返回值;
  3. 不管写在属性里面的js代码还是哪里的都需要加 {}
  4. 客户端能自动刷新原理:因为里面有websocket技术
  5. 类组件的 this 指向实例对象,而函数组件没有 this,打印为undefined;
  6. 修改state状态,只能用this.setState(),不同于Vue的getter&setter,注意:直接修改state数据无法刷新页面;
  7. 在 Vue 中,默认提供了v-model指令,可以很方便的实现 数据的双向绑定; 但是,在 React 中,默认只是单向数据流,也就是 只能把 state 上的数据绑定到 页面,无法把 页面中数据的变化,自动同步回 state ; 如果需要把 页面上数据的变化,保存到 state,则需要程序员手动监听onChange事件,拿到最新的数据,手动调用this.setState({ }) 更改回去;
  8. 代码中的 点击事件 onClick={this.removeItem.bind(this,item.id)} 这里不能写成 onClick={this.removeItem(item.id)}因为执行时会立即调用,不用点击就触发了函数调用,比如 fn()调用函数,所以这里使用 bind 因为bind 返回一个函数。
  9. render方法里面有默认的this指向,而自定义方法没有,需要改变this指向;
  10. 为什么用bind 不用call和apply呢?因为call和apply改变后会先执行调用一次改变this后的函数
  11. 多次对一个函数使用bind 改变this指向 不影响,因为 bind只会在第一次改变,后期改不了;
  12. 建议初始化时,先对自定义方法使用bind 改变this指向
  13. bind 传参时:bind(target,...args) , 只在第一次生效;
  14. refs:回调函数、 React.createRef();
  15. 什么时候用到re?:当需要用到节点时,比如音频视频等 用 ref 获取节点

数据的挂载方式

1、数据绑定

  • 单向:{}
  • 双向:value和 onChange 事件
    2、列表循环
  • map()
  • filter()
    注意:key 的属性 同级和同类型的才会添加key 不是同级和同类别的不用加key
    因为有key的话 内部的diff算法更快,如果没有也不会报错,可能影响数据的修改更新

3、事件绑定

  • event:事件处理函数的最后一个参数
  • this的指向:bind 传参时:bind(target,...args) , 只在第一次生效;

4、refs

  • 回调函数
  • React.createRef()
// 字符串    // 获取: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事件;

2、非受控组件:表单元素不受state / props控制,通过节点方式获取;

  • 原生
  • refs

state

组件的状态

  • 读取:this.state.xxx
  • 修改:this.setState() 原则:创建新的数据并覆盖

props 组件通讯

组件通讯:

1、父子通讯:props;

  • 父组件操作:定义属性并传递数据
  • 子组件操作:函数组件:函数的第一个参数、类组件:this.props

2、子父通讯:把父组件的方法传到子组件去执行并传递参数;

  • 父组件操作:定义方法并通过props传入子组件 (数据在哪里就把方法定义在哪里)
  • 子组件操作:执行方法并传递参数

3、兄弟通讯:状态提升

  • 把状态放到兄弟组件的共同的父级

4、多层次组件通讯;

  • 逐层传递 :一层一层传递(比较繁琐)
  • Context

1、创建Context ;

2、父组件操作:Provider 共享数据 其中的 value;
3、子组件操作:接收数据 ;分为函数组件 :Consumer / 类组件 : Consumer 和 this.context

转载地址:http://nnomz.baihongyu.com/

你可能感兴趣的文章