淘先锋技术网

首页 1 2 3 4 5 6 7

一.React 组件的两种创建方式

1.使用函数创建组件

  • 使用 JS 中的函数创建的组件叫做: 函数组件
  • 函数组件必须有返回值
  • 组件名称必须以大写字母开头,React 据此区分组件和普通的React 元素
  • 使用函数名作为组件标签名
// 函数组件
// 第一种
// function Hello(){
//     return (
//         <div>react组件</div>
//     )
// }
// 第二种  必须要有返回值
// function Hello(){
//     return null;
// }
// 第三种
const Bac = () => (
    <div>
      <ul>
        {list.map((item) => <li key={item.id}>{item.name}</li>)}
      </ul>
    </div>
)
const Hello = () => <div>我是react的函数组件</div>
ReactDOM.render(<Hello />,document.getElementById('root'))

2.使用类创建组件

  • 类组件: 使用 ES6 的 class 创建的组件
  • 类名称必须以大写字母开头
  • 类组件应该继承 React.Component 父类,从而可以使用父类中提供的方法或属性
  • 类组件必须提供 render() 方法
  • render() 方法必须有返回值,表示该组件的结构
// 类创建组件
class Hello extends React.Component {
    render() {
        return (
            <div>我是React的类组件</div>
        )
    }
}
// 渲染组件
ReactDOM.render(<Hello />,document.getElementById('root'));

3.我们可以把组件抽离为独立JS文件

步骤:

  1. 创建 Hello.js
  2. 在 Hello.js 中导入 React
  3. 创建组件(函数组件 或者 类组件)
  4. 在 Hello.js 中导出该组件
  5. 在 index.js 中导入 Hello 组件
  6. 渲染组件
// Hello.js
import React from 'react';
class Hello extends React.Component {
    render() {
        return (
            <div>我是抽离出来的Hello.js</div>
        )
    }
}
export default Hello;
// index.js
import Hello from './Hello.js';
const root = document.getElementById('root');
// 渲染组件
ReactDOM.render(<Hello />,root);

二.React 事件处理

1.事件绑定

  • React 事件绑定语法 与 DOM 事件语法相似
  • 语法: on+事件名称={事件处理程序}
  • 注意点: React 事件采用驼峰命名法,如: onClick,onFocus
const root = document.getElementById('root');

class Hello extends React.Component {
    handlerClick(){
        console.log('触发了点击事件')
    }
    render(){
        return (
            // <button onClick={this.handlerClick}>点击事件</button>
            <button onClick={()=>alert('111111111111')}>点击事件</button>
        )
    }
}

// 渲染组件
ReactDOM.render(<Hello />,root);

2.事件处理

  • 可以通过事件处理程序的参数获取到事件对象
  • React 中的事件对象叫做: 合成事件(对象)
  • 合成事件: 兼容所有浏览器,无需担心跨浏览器兼容性问题
const root = document.getElementById('root');

class Hello extends React.Component {
    handlerClick(e) {
        // 阻止浏览器的默认行为
        e.preventDefault();
        console.log('触发了点击事件')
    }
    render() {
        return (
            // <button onClick={this.handlerClick}>点击事件</button>
            <div>
                <button onClick={() => alert('11111111')}>点击事件</button>
                <a href="https://react.docschina.org/docs/components-and-props.html" onClick={this.handlerClick}>react</a>
            </div>
        )
    }
}

// 渲染组件
ReactDOM.render(<Hello />, root);

三.有状态组件(函数组件)和无状态组件(类组件)

  • 函数组件又叫做无状态组件,也就是它没有自己的状态,只负责数据显示
  • 类组件叫做有状态组件,就是有状态组件,它可以对数据进行更新

1.组件中的 state 和 setState

  1. state 的基本使用和获取
  • 状态即是数据(state),它是组件内部私有的数据,只能在组件内部使用
  • state 的值是对象,表示一个组件中可以有多个数据
  • 可以通过 this.state 来获取状态
// 第一种方式
class Comp extends React.Component {
  constructor(){
  	super()
  	// 初始化 state
    this.state = {
      count:0
    }
  }
  render() {
    return (
      <div>
        <li>{this.state.count}</li>
        <div>有状态组件</div>
      </div>
    )
  }
}
第二种方式
class Comp extends React.Component {
// 简化写法
  state = {
    count:0
  }
  render() {
    return (
      <div>
        <li>{this.state.count}</li>
        <div>有状态组件</div>
      </div>
    )
  }
}
  1. 修改state的数据
  • 语法: this.setState({要修改的数据})
  • 注意:不可以直接修改 state 中的值,这是错误的
  • setState({}) 的作用:修改 state,更新视图
// 正确修改 state 中的数据
this.setState({
	count:this.state.count + 1
})
// 错误修改 state 中的数据
this.state.count += 1

2.事件绑定 this 指向

  1. 箭头函数
  • 利用箭头函数自身没有this的特点
  • render() 方法中的this为组件实例可以获取到 setState()
class Hll extends React.Component {
    handlerClick(e) {
        // 阻止浏览器的默认行为
        e.preventDefault();
        console.log('触发了点击事件')
    }
    state = {
        count:2
    }
    // 事件处理程序
    onIncrement(){
        this.setState({count:this.state.count + 10})
        console.log(this)
    }
    render() {
        // 箭头函数中的this指向外部环境,此处为: render()
        return (
            // <button onClick={this.handlerClick}>点击事件</button>
            <div>
                <div>{this.state.count}</div>
                <button onClick={()=> this.onIncrement()}>点击+10</button>
            </div>
        )
    }
}
// 渲染组件
ReactDOM.render([<Hello />,<Hll />], root);
  1. class 的实例方法(推荐)
  • 利用箭头函数形式的class实例方法
  • 由于babel的存在可以直接使用
class Hll extends React.Component {
    state = {
        count: 0
    }
    // 事件处理程序    class实例方法用箭头函数
    onIncrement = () => {
        console.log(this)
        this.setState({count: this.state.count + 10})
    }
    render() {
        return (
            <div>
                <h2>{this.state.count}</h2>
                <button onClick={this.onIncrement}>点击+10</button>
            </div>
        )
    }
}
// 渲染组件
ReactDOM.render([<Hello />,<Hll />], root);

3.表单处理

  1. 受控组件的概念
  • React中可变状态通常保存在 state 中,并且只能通过 setState() 方法来修改
  • React将state与表单元素值value绑定到一起,由 state 的值来控制表单元素的值
<input type="text" value={this.state.count} 
     onChange={e => this.setState({count:e.target.value})}
/>
  1. 受控组件的使用步骤
1.在 state 中添加一个状态,作为表单元素的value值
state = {
     count: 0
}
2.给表单元素绑定 change 事件,将表单元素的值设置为 state 的值 (控制表单元素值的变化)
<input type="text" value={this.state.count} 
      onChange={e => this.setState({count:e.target.value})}
/>

4.非受控组件

使用步骤:

  1. 调用 React.createRef() 方法创建一个 ref 对象
constructor(){
	super()
	this.txtRef = React.createRef()
}
  1. 将创建好的 ref 对象添加到文本框中
  1. 通过 ref 对象获取到文本框的值

注意点:表单数据由DOM本身处理。即不受setState()的控制

四.组件的props

  • 组件是封闭的,要接收外部数据应该通过 props 来实现
  • props 的作用: 接收传递给组件的数据
  • 接收数据:注意:函数组件通过参数 props 接收数据,类组件通过 this.props 接收数据
<Hello2 name='张三' age={20} tag={<h1>呵呵呵呵</h1>} />
function Hello2(props) {
  console.log(props)
  return (
	<div>接收到数据:{props.name}</div> // 张三	
  )
}
class Hello2 extends React.Component {
  render() {
    return (
      <div>
        {this.props.age}    // 20
      </div>
    )
  }
}

props 的特点:

  • props 是只读的对象,只能读取属性的值,无法修改对象
  • 注意点:如果使用类组件时,写了构造函数,应该将 props 传递给 super() ,否则,无法在构造函数中获取到props
class Hello extends React.Component {
  constructor(props){
    // 推荐将 props 传递给父类构造函数
	super(props)
  }
  render() {
    return (
      <div>
        {this.props.age}    
      </div>
    )
  }
}

1.父组件传递数据给子组件

  1. 父组件提供要传递的state数据
  2. 给子组件标签添加属性,值为 state 中的数据
  3. 子组件中通过 props 接收父组件中传递的数据
// 父传子
class Parent extends React.Component {
  state = {
    lastName: '小明'
  }
  render() {
    return (
      <div>
        父组件向子组件传递数据 <Child name={this.state.lastName} />
      </div>
    )
  }
}
function Child(props) {
  console.log(props)
  return (
    <div>
      <h1>子组件接收父组件数据: {props.lastName}</h1>
    </div>
  )
}
ReactDOM.render(
  [<Parent />],
  document.getElementById('root'),
  ()=> console.log('渲染成功')
);

2.子组件传递数据给父组件

  1. 父组件提供一个回调函数(用于接收数据)
  2. 将该函数作为属性的值,传递给子组件
  3. 子组件通过 props 调用回调函数
  4. 将子组件的数据作为参数传递给回调函数
// 子传父
// 父组件
class Parents extends React.Component {
  state = {
    lastName:''
  }
  // 调用回调函数用来接收数据
  handlers = (data) => {
    console.log('子组件向父组件传递的数据:',data)
    this.setState({
      lastName:data
    })
  }
  render() {
    return (
      <div>
        <h1>父组件接收数据: {this.state.lastName}</h1>
        // 将该函数作为属性的值,传递给子组件
        <Childs msg={this.handlers} />
      </div>
    )
  }
}
// 子组件
class Childs extends React.Component {
  state = {
    lastName:'密码'
  }
  handlerClick = () => {
    console.log(this.props)
    // 子组件调用父组件中传递过来的回调函数
    // 将子组件的数据作为参数传递给回调函数
    this.props.msg(this.state.lastName)
  }
  render() {
    return (
      <div>
        <button onClick={this.handlerClick}>点击传数据</button>
      </div>
    )
  }
}

3.兄弟组件

  • 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
  • 公共父组件职责:1.提供共享状态 2.提供操作共享状态的方法
// 兄弟组件
class Parentss extends React.Component {
  state = {
    count:0
  }
  handlerClick = () => {
    this.setState({count:this.state.count + 1})
  }
   render() {
     return (
       <div>
         <Child1 count={this.state.count} />
         <Child2 count2={this.handlerClick} />
       </div>
     )
   }
}
const Child1 = (props) => {
  return (
    <div>
      {props.count}
    </div>
  )
}
const Child2 = (props) => {
  return (
    <div>
      <button onClick={() => props.count2()}>+1</button>
    </div>
  )
}

4.跨组件接收数据 Context

1.调用 React.createContext() 创建 Provider(提供数据)Consumer(消费数据) 两个组件
const {Provider,Consumer} = React.createContext()
// 兄弟组件
class Parentss extends React.Component {
  state = {
    count:0
  }
  handlerClick = () => {
    this.setState({count:this.state.count + 1})
  }
   render() {
     return (
       // 2.使用 Provider 组件作为父节点
       // 3.设置 value 属性,表示要传递的数据
       <Provider value={this.state.count}>
         <div>
          <Child1 count={this.state.count} />
          <Child2 count={this.handlerClick} />
        </div>
       </Provider>
       
     )
   }
}
const Child1 = (props) => {
  return (
    <div>
      {props.count}
    </div>
  )
}
const Child2 = (props) => {
  return (
    <div>
      <button onClick={() => props.count()}>+1</button>
      <Child3 />
    </div>
  )
}
const Child3 = () => {
  return (
    <div>
      <div>11111111</div>
      // 4.调用 Consumer 组件接收数据   data 就是value的属性值
      <Consumer>
        {data => <span>接收到的数据: {data}</span>}
      </Consumer>
    </div>
      
  )
}

总结:今天学习了组件的两种创建方式,有状态组件和无状态组件,还有组件之间的通信.