React基础学习(第三天)

条件渲染

1. if / else

  render () {
    if (this.state.isLoading) { // 正在加载中
      return <h1>Loading...</h1>
    }
    return <div>这就是我们想要的内容</div>
  }
// 钩子函数 五秒钟之后 修改状态值
  componentDidMount () { 
    setTimeout(() => {
      this.setState({
        isLoading : false
      })
    }, 3000);
  }

2. 三元表达式

 return this.state.isLoading ? (<h1>Loading...</h1>) : (<div>这就是我们想要的内容</div>)

3. 逻辑运算符

 return this.state.isLoading && (<h1>Loading...</h1>) 

列表渲染

遍历1

// 准备数据
state = {
  list :['小苹果','大香蕉','黄橙子']
}

return (<ul>
    {this.state.list.map(item => { 
       return <li>{ item }</li>
     }) }
</ul>)

遍历2

// 准备数据
state = {
    list2: [{ id: 1, name: '春' }, { id: 2, name: '飞' }, { id: 3, name: '莲' }]
}
// 遍历
 return (
      <ul>
        {this.state.list2.map(item => { 
          return <li key={item.id}>{ item.name }</li>
        }) }
      </ul>
    )

提取到函数

// render 钩子函数
render () {
  return (<ul>
        { this.renderLi()  }
       </ul>)
 }
  
// 提取到的一个函数
// 必须要有返回值
renderLi () { 
  return this.state.list2.map(item => { 
     return <li key={item.id}>{ item.name }</li>
    }) 
}

处理样式

行内样式

// 这个{{}} 不是双括号语法,  而是单括号里面有个 样式对象
//{} 可以拿到原始类型
<div style={{ color: 'pink', backgroundColor: 'yellowgreen', height: 300 }}>

外联样式

//1. 外部 index.css
.red {
  color: red;
  font-size: 50px;
}

//2. 引入
import './index.css'

//3. 添加类
 <p className='red' >哈哈</p>

评论案例

步骤

  • 准备数据 - 列表展示

  • 受控组件

  • 表单头部展示收集数据

  • 补充 : 非受控组件

评论案例1 : 列表展示

  • 准备数据
 list: [
      { id : 1, username :'张三', content :'做一个凡人' },
      { id : 2, username :'李四', content :'贪财好色' },
      { id : 3, username :'王五', content :'一身正气' }
    ],
  • 展示
<ul>
    {this.state.list.map(item => { 
        return (<li key={item.id}>
                <p>评论人 : {item.username}</p>
                <p>评论内容 : {item.content}</p>
            </li>)
        }) }
</ul>

评论案例2 : 受控组件

  • 见下面的受控组件模块

评论案例3 : 头部展示

  • 结构
<div>
  评论的人 :
    <input
    onChange={e => this.getValues('username', e.target.value)}    # +
    name="username"
    value={username}
    style={{ width: '214px' }}
    type="text"
    />
  <br />
  评论内容 :
    <textarea
    onChange={e => this.getValues('content', e.target.value)}    # +
    name="content"
    value={content}
    cols="30"
    rows="10"
    ></textarea>
    <button onClick={this.add}>添加评论</button>
</div>
  • 处理表单数据
getValues = (name, value) => {
  this.setState({
 		 [name]: value
  })
}
  • 添加评论
  add = () => { 
    // 获取数组
    const { list, content, username } = this.state 
    let obj = {
      id: +new Date(),
      content,
      name : username
    }
    this.setState({
      list: [obj, ...list],
      content: '',
      username :''
    }) 
  }

评论案例4 : 非受控组件

  • 见 下面 非受控组件模块

受控组件

导入 : 给 input 添加了一个value ,展示默认值

受控组件介绍

  • 表单元素 是用来收集数据的

  • react 表单元素分为 : 受控组件 + 非受控组件

  • 受控组件 : 受 React 控制的组件

  • 如何成为受控组件 ? 给 input 添加value 值, 那么这个input 就成了受控组件

  • M ==> V , V ==> M (我们自己处理)

- 1.需要给 input 添加 value 并且赋值 =>  M ==> V
- 2.onChange={ this.handleInput } ==> 监听 V 的数据变化, 收集值赋值给 M  
- 3. 
  handleInput = (e) =>  {
      // 监听input 的变化
      //  (V) 拿到文本框的值, 修改 state 里面的数据(M)
      console.log(e,target.value)
      
      // 修改状态
      this.setState({
          username : e.target.value
      })
  }

其他表单处理受控组件

// 文本输入框
<input onChange={this.handleInput} value={username} type="text" />  <br />
// 文本域
<textarea onChange={this.handleTextarea} value={content} cols="30" rows="10"></textarea>
// 下拉框
<select value={city} onChange={this.handleSelect}>
    <option value="sh">上海</option>
    <option value="hz">杭州</option>
    <option value="bj">北京</option>
</select>
  • 处理
  // 处理 input 
  handleInput  = (e) => { 
    this.setState({
      username: e.target.value
    })
  }
  // 同上
.....

优化1

// 让其他表单都绑定到一个事件中
// 文本输入框
<input name='username' onChange={this.handleInput} value={username} type="text" />  <br />
// 文本域
<textarea name='content' onChange={this.handleTextarea} value={content} cols="30" rows="10"></textarea>
// 下拉框
<select name='city' value={city} onChange={this.handleSelect}>
    <option value="shanghai">上海</option>
    <option value="hangzhou">杭州</option>
    <option value="beijing">北京</option>
</select>
  • 处理
  handle = e => { 
    // console.log(e.target.name);

    this.setState({
      [e.target.name] : e.target.value
    })
  }

优化2

// 文本输入框
<input  onChange={(e) => this.getValues('username', e.target.value)} value={username} type="text" />  <br />
// 文本域
<textarea onChange={(e) => this.getValues('content', e.target.value)} value={content} cols="30" rows="10"></textarea>
// 下拉框
<select value={city} onChange={ (e) => this.getValues('city', e.target.value) }>
    <option value="shanghai">上海</option>
    <option value="hangzhou">杭州</option>
    <option value="beijing">北京</option>
</select>
  • 处理
 getValues = (name, value) => { 
    this.setState({
      [name] : value
    })
  }

非受控组件

导入 : 如果不想让inptu 成为受控组件 , 又想添加默认值

####非受控组件介绍:

  • 添加 defaultValue : <input type="text" defaultValue={this.state.name} />
  • 它默认就是一个非受控组件
  • 非受控组件操作 DOM 直接获取 数据 – 通过 ref

使用步骤

  • 1-创建 ref 引用
constructor(){
  super()
	// 方式1
  this.iptRef = React.createRef()
}
// 和 state 一样
// 方式2: 属性初始化语法
iptRef = React.createRef()
  • 2-绑定 ref
<input ref={ this.iptRef } />
  • 3-获取数据
// 可以通过尝试点击按钮
click = () => {
    console.log(this.iptRef.current.value)
}

组件通讯

父传子

  • 通过普通的props属性传递, 实现父传子即可
// 父组件
class Parent extends React.Component {
  // 1. 准备好数据
    state = {
      pName : '父的数据'
    }
    render() {
      return (
        <div>
          <p>哈哈</p>
          //2. 通过属性 将数据传递给子组件
          <Child name={this.state.pName}></Child>
        </div>
      )
    }
}
// 子组件  
// 3. 通过 props 获取数据
const Child = (props) => <div>子组件 { props.name }</div>

子传父

  • 思路 : 父组件中提供了一个方法, 由子组件调用这个方法, 将数据作为参数传递给父组件
  • 步骤 :
    • 1-在父组件中提供一个方法
    • 2-将这个方法通过属性传递给子组件
    • 3-子组件中通过props 拿到这个方法调用, 并且将数据作为参数传递
// 父组件
class Parent extends React.Component {
    // 第一步 :父组件准备一个方法
    pFn = (data) => { 
      console.log('调用了',data);
    }
    render() {
      return (
        <div>
          <p>哈哈</p>
          {/* 第二步 : 通过属性将方法产传递给子组件 */}
          <Child cfn={ this.pFn } ></Child>
        </div>
      )
    }
}
// 子组件  
class Child extends React.Component { 
  render () { 
    return (<div>
      <button onClick={this.sendMsg}>点击发送</button>
    </div>)
  }
  sendMsg = () => { 
    // 第三步 : 子组件通过props 拿到这个方法, 并且传参
    this.props.cfn('撩汉子')
  }
}

兄弟组件通讯

  • 思路 : 状态提升

改造评论案例 ★

  • 组件化

    • index.js => Comments父组件
    • components/
      • CommentsList.js ==> CommentsList 列表组件
      • CommentsLForm.js ==> CommentsLForm 表单组件
  • 父传子 => 把 list 传给 CommentsList 组件 => 遍历展示列表

  • 子传父 => 把表单里的数据新对象 => 点击添加评论 => 传给 Comments组件

  • pGetData

  • 添加评论

context

  • 使用场景 : 跨多层组件传递数据
    • 如果两个组件是 远房亲戚 的关系,此时,就可以使用 Context 来通讯。
  • 画图 : One > Two > Three > Four
  • Context 中提供了两个组件
    • Provider 组件 : 提供组件, 提供数据
    • Consumer 组件 : 消费组件, 接收数据
// 1. 创建 Context 对象, 并解构出来两个组件
const { Provider, Consumer } = React.createContext()    # +

//2. 类组件
class One extends React.Component {
  state = {
    color :'red'
  }
  render() {
    return (
      // 第二步 : 使用 Provider 组件包裹 one组件, 只有被包裹的部分里面才能获取数据 
      // 通过 value 属性提供要共享的数据
      <Provider value={ this.state.color }>          # +
        <div>
          <p> One </p>
          <Two></Two>
        </div>
      </Provider>
    )
  }
}
class Two extends React.Component {
....
}
class Three extends React.Component {
	....
}
class Four extends React.Component {
  render() {
    return (
      <div>
        <p>Four</p>
        {/* 3.在 Four 组件中, 通过 consumer 来获取数据 */}
        {/* 遵循的是 render-props 思想 后面介绍 */}
        <Consumer>
          {data => { 
            return <p style={{ color : data }} >这是测试用的</p>   # +
          }
             }
        </Consumer>
      </div>
    )
  }
}

猜你喜欢

转载自blog.csdn.net/weixin_44694682/article/details/107673604