react基础到实战-尚硅谷(学习笔记二)

接上一条博客的内容,再次附上视频教程的学习地址
链接:https://www.bilibili.com/video/BV184411x7F9
上一篇文章链接:https://blog.csdn.net/AtalantaDavis/article/details/108244938

React测试示例的步骤

  1. 定义组件
//方式1:工厂函数组件(简单组件)
function MyComponent(){
    return <h2>工厂函数组件(简单组件)</h2>
}
//方式2:ES6类组件(复杂组件)
class MyComponent2 extends React.Component {
    render () {
        return <h2>ES6类组件(复杂组件)</h2>
    }
}
  1. 渲染组件标签
ReactDOM.render(<MyComponent />,document.getElementById('example1'))
ReactDOM.render(<MyComponent2 />,document.getElementById('example1'))

在组件类里面打印this,指向Mycomponent2标签

组件的三大属性

state

是个对象,俗称状态机,有状态不能用工厂模式

编码操作
  1. 初始化状态
constructor(props) {  // 固定写法
    super(props)  // 调用,将props传给父类型
    // 初始化状态
    this.state = {
        stateProp1:value1,
        stateProp2:value2
    }
}
  1. 读取某个状态值
 this.state.stateProp1=value2
  1. 更新状态
this.setState()
示例步骤
  1. 定义组件
class Like extends React.component{
    constructor(props) {  // 固定写法
        super(props)  // 调用,将props传给父类型
        // 初始化状态
        this.state = {
            isLike: false
        }
        // 将新增的方法中的this强制绑定为组件对象
        this.handleClick = this.handleClick.bind(this)
    }
    // 新添加方法:内部的this默认不是组件对象,而是undefined
    handleClick () {
        // 得到状态
        const isLike =!this.state.isLike
        this.setState({isLike})
    }
    // 重写组件类的方法
    render(){
        const {isLikeMe} = this.state
        return <h2 onClick={this.handleClick}>{isLike?'你喜欢我':'我喜欢你'}</h2>
    }
}
  1. 渲染组件标签
ReactDOM.render(<Like />,document.getElementById('example1'))
props

对象

编码操作
  1. 对props中的属性值进行类型限制和必要性限制,引入prop-type.js
Person.propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number
}
  1. 指定属性默认值
Person.defaultProps = {
    sex: '男',
    age: 18
}
  1. 标签简写
ReactDOM.render(<Person {...p1} /> ,document.getElementById('example1'))

...的作用:1.打包 ;2.解包

示例步骤
  1. 定义组件
function Person(props) {
    return (
        <ul>
            <li>姓名:{props.name}</li>
            <li>年龄:{props.age}</li>
            <li>性别:{props.sex}</li>
        </ul>
    )
}


  1. 渲染组件标签
const p1 = {
    name: 'Tom',
    age: 18,
    sex: '女'
}

ReactDOM.render(<Person name={p1.name} age={p1.age} sex={p1.sex} />,document.getElementById('example'))
refs
示例步骤
  1. 定义组件
class myComponent extends React.componenet {
    constructor(props) {
        super(props)
        this.showInput = this.showInput.bind(this)
        this.handleBlur = this.handleBlur.bind(this)
    }
    
    showInput() {
        const input = this.refs.content
        alert(this.input.value)
    }
    handleBlur(event){
        alert(event.target)
    }
    
    render() {
        return (
            <div>
                <input type="text" ref="content"/>
                <input type="text" ref={input => this.input = input}/>
                <button onClick={this.showInput]>提示输入</button>
                <input type="text" placeholder="失去焦点提示内容" onBlur={this.handleBlur}>
            </div>
        )
    }
}
  1. 渲染组件标签
ReactDOM.render(<MyComponent />,document.getElementById('example'))
三种特点总结

state 数据从组件内部传来
props 数据从组件外部传来
refs

组件化编码流程

  1. 拆分组件:拆分界面,抽取组件
  2. 实现静态组件:使用组件实现静态页面效果
  3. 实现动态组件
    1. 动态显示初始化数据
    2. 交互功能
示例
// 1. 定义组件
// 问题:数据保存在哪个组件里// 看数据是某个组件需要(给他),还是某些组件需要(给共同的父组件)
// 问题2:需要在子组件中改变负组件的状态
// 子组件中不能直接改变父组件的状态
// 状态在哪个组件,更新状态的行为就应该定义在那个组件// 解决:父组件定义函数,传递给子组件,子组件调用
class App extends React.Component {
    constructor(props) { 
        super(props); 
        this.state = {
            todos:["111","222","22","333"]   
        }    
        this.addTodo = this.addTodo.bind(this)  
    }  
    addTodo (todo) { 
        const {todos} = this.state    
        todos.unshift(todo)    
        // 更新状态   
        this.setState({todos}) 
    }  
    render () {    
        const {todos} = this.state    
        return (            
            <div>              
                <h1>Simple ToDo List</h1>              
                <Add count={todos.length} addTodo={this.addTodo} /> 
                <List todos={todos}/>            
            </div>    
        )  
    }
}
class Add extends React.Component {  
    static propTypes = {    
        count: PropTypes.Number 
   }  
   constructor(props) {    
        super(props);    
        this.AddMessage = this.AddMessage.bind(this)  
   } 
   AddMessage () {    
   // 1.读取输入的数据    
   const todo = this.todoInput.value.trim()    
   // 2.检查合法性    
   if(!todo){      
        return;    
   }   
   // 3.添加    
   this.props.addTodo(todo)   
   //  4.清除输入    
   this.todoInput.value = ""  
   }  
   render () {    
       return (            
        <div>              
            <input type="text" ref={input=> this.todoInput = input}/>               
            <button onClick={this.AddMessage}>add #{this.props.count + 1}   
            </button>            
         </div>    
         )  
      }
 }
 class List extends React.Component {  
    static propTypes = {    
        todos: PropTypes.array,    
        addTodo: PropTypes.func 
   }  
   render () {    
        return (            
            <ul>              
                {this.props.todos.map((todo, index) => <li key={index}>{todo}</li>)}            
            </ul>    
        )  
   }
}
// 2. 渲染UI
ReactDOM.render(<App />, document.getElementById("example"))

组件提交提交表单数据

两种方式获取表单数据
受控组件:表单项输入数据能自动收集成状态,如示例中密码的获取方式,用state,根据react思想更支持受控组件
非受控组件:需要手动读取表单数据,如示例中用户名的获取方式,用refs,更轻松

示例编码
/*
      * 自定义包含表单的组件
      * 1. 界面如下所示
      * 2. 输入用户名密码后,点击登录提示输入信息
      * 3,不提交表单
      * */
      class LoginForm extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            pwd: ''
          }
          this.handleSubmit = this.handleSubmit.bind(this)
          this.handleChange = this.handleChange.bind(this)
        }
        handleSubmit (event) {
          const name = this.nameInput.value
          const {pwd} = this.state
          alert(`准备提交的用户名${name},密码为${pwd}`)
          //阻止事件的默认提交
          event.preventDefault()
        }
        handleChange (event) {
          // 读取输入的值
          const pwd = event.target.value
          // 更新pwd的状态
          this.setState({pwd})
        }
        render() {
          return (
              <form action="/test" onSubmit={this.handleSubmit}>
                用户名:<input type="text" ref={input => this.nameInput = input} />
                密码:<input type="password" value={this.state.pwd} onChange={this.handleChange} />
                <input type="submit" value="登录" />
              </form>
          )
        }
      }

      ReactDOM.render(<LoginForm />, document.getElementById("example"))

组件的生命周期

生命周期函数

在这里插入图片描述
在这里插入图片描述

渲染过程
回调函数小知识

虚拟DOM挂在到真实容器上的过程叫挂载
回调函数:我定义的但是我没调用,但是它执行了
命令式编程:每一步都要自己写

生命周期流程
  • 第一次初始化渲染显示:ReactDOM.render()

constructor():创建对象初始化state
componentWillMount():将要插入回调
render():用于插入虚拟DOM回调
componentDidMount():已经插入回调

  • 每次更新state:this.setState()

componentWillUpdate():将要更新回调
render():更新(重新渲染
componentDidUpdate():已经更新回调
componentDidMount():已经插入回调,插入完成后运行

  • 移除组件:ReactDOM.unmountComponentAtNode(containerDom)

componentWillUnmount():组件将要被移除回调

重要的勾子

render():初始化渲染或更新渲染调用
componentDidMount():开启监听,发送ajax请求
componentWillUnmount():做一些收尾工作,如:清理定时器
componentWillReceiveProps():当props发生改变时,会执行此操作,旧的props还可以通过this.props来获取。

示例编码
      class Life extends React.Component {
        constructor(props) {
          super(props);
          // 初始化状态
          this.state = {
            opacity: 1
          }
          this.distroyComponent = this.distroyComponent.bind(this)
        }
        componentDidMount () { //生命周期,挂载完成之前加载的函数
          this.intervalId = setInterval(function() {
            console.log("定时器执行....")
            let {opacity} = this.state
            opacity -= 0.1
            if(opacity<=0){
              opacity = 1
            }
            this.setState({opacity})
          }.bind(this), 100)
        }
        distroyComponent () {
          // 此生命周期用来卸载组件所在的DOM元素
          ReactDOM.unmountComponentAtNode(document.getElementById("example"))
        }
        componentWillUnmount () {
          // 此生命周期:在卸载挂载的DOM元素之前,运行的函数
          // 清理定时器,如果不清理定时器,在卸载挂载之后还会继续定时
          clearInterval(this.intervalId)
        }
        render (){
          const {opacity} = this.state
          return (
              <div>
                <h2 style={{opacity:opacity}}>{this.props.msg}</h2>
                <button onClick={this.distroyComponent}>不活了</button>
              </div>
          )
        }
      }

      ReactDOM.render(<Life msg="react太难了!"/>,document.getElementById("example"))
    

虚拟DOM与DOM Diff算法

初始化过程
更新界面
创建虚拟DOM树
真实DOM树
绘制界面显示
setState更新状态
新/旧树比较差异
更新差异对应真实DOM
局部界面重绘

下一篇文章链接:https://blog.csdn.net/AtalantaDavis/article/details/108342941

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AtalantaDavis

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值