JSX基本使用&React(1)

2022-01-16  本文已影响0人  鲜蛋卷小狐狸
  1. React元素的属性名使用驼峰命名法
  2. 特殊属性名:class -> className for -> htmlFor tabindex -> tabIndex
  3. 没有子节点的React元素可以用/>结束
  4. 推荐:使用小括号包裹JSX,从而避免JS中的自动插入分号陷阱
const dv = (
   <div>hello</div>
)
  1. jsx中是使用Javascript表达式
const name = 'jack'
const dv = (
   <div>你好,我叫{name}</div>
)

6.条件渲染

// 条件渲染
const isLoading = true
const loadData = () => {
  if(isLoading){
    return <div>loading...</div>
  }
  return <div>数据加载完成,此处显示加载后的数据</div>
}

const title = (
  <h1>条件渲染:{loadData()}</h1>
)
ReactDOM.render(title,document.getElementById('root'))

还可以使用if/else三元运算符逻辑与运算符来实现

//三元表达式
const loadData = () => {
  return isLoading ? (<div>loading...</div>) : (<div>数据加载完成,此处显示加载后的数据</div>)
}
//逻辑与运算符
const loadData = () => {
  return isLoading && (<div>loading...</div>)
}

isLoading是false不会执行后面的,true才会执行
7.列表渲染

const songs = [
  {name:'qwe',id:1},
  {name:'dfddg',id:2},
  {name:'hsd',id:3}
]

const title = (
  <ul>
    {songs.map(item => <li key={item.id}>{item.name}</li>)}
  </ul>
)

注意:

8.JSX样式处理

const list = (
  <h1 style={{color:'red',backgroundColor:'skyblue'}}>
    jsx样式处理
  </h1>
)
//导入
import './index.css'
const list = (
<h1 className="title" style={{color:'red',backgroundColor:'skyblue'}}>
    jsx样式处理
  </h1>
)
//index.css
.title{
  text-align: center;
}

9.react组件的两种创建方式

function Hello(){
  return(
    <div>我的第一个react组件!</div>
  )
}
ReactDOM.render(<Hello />,document.getElementById('root'))

箭头函数

const Hello = () => <div>我的第一个react组件</div>
class Hello extends React.Component{
  render(){
    return(
      <div>我的第一个react类组件!</div>
    )
  }
}

9.3 抽离为独立的js文件
组件作为独立的个体,独立存放一个组件

10.点击事件:驼峰命名法,

// 通过函数组件绑定事件
function App() {
  function handleClick(){
    console.log('函数组件中的事件绑定,事件触发了')
  }
  return(
    <button onClick={handleClick}>点我,点我</button>
  )
}
ReactDOM.render(<App />,document.getElementById('root'))
class  App extends React.Component{
    handleClick(){
        console.log('单击事件触发了')
    }
    render(){
        return(
            <button onClick={this.handleClick}>点我,点我</button>
        )
    }
}
ReactDOM.render(<App />,document.getElementById('root'))

11.事件对象

12.有状态组件和无状态组件

13.组件中的state和setState

this.setState({
  number: this.number + 1
})

14.抽离onclick的方法,解决this指向问题

class App extends React.Component{
    state = {
        count: 0, 
    }
    onIncrement() {
        this.setState({
            count: this.state.count + 1
        })
    }
    render(){
        return(
        <div>
            <h1>计数器:{this.state.count}</h1>
//箭头函数中的this指向外部环境,此处为:render()方法
            <button onClick={()=>this.onIncrement()}>+1</button>
        </div>
        ) 
    }
}
class App extends React.Component{
    state = {
        count: 0, 
    }
    constructor() {
      super()
      this.onIncrement = this.onIncrement.bind(this)
    }
    onIncrement() {
        this.setState({
            count: this.state.count + 1
        })
    }
    render(){
        return(
        <div>
            <h1>计数器:{this.state.count}</h1>
//箭头函数中的this指向外部环境,此处为:render()方法
            <button onClick={this.onIncrement}>+1</button>
        </div>
        ) 
    }
}
class App extends React.Component{
    state = {
        count: 0, 
    }
    onIncrement = () => {
        this.setState({
            count: this.state.count + 1
        })
    }
    render(){
        return(
        <div>
            <h1>计数器:{this.state.count}</h1>
            <button onClick={this.onIncrement}>+1</button>
        </div>
        ) 
    }
}

15.表单处理

class App extends React.Component{
   state = {txt:''}
    handleChange = e => {
        this.setState({
            txt:e.target.value
        })
    }
    render(){
        return(
        <div>
            <input type="text" value={this.state.txt} onChange={this.handleChange}>+1</input>
        </div>
        ) 
    }
}
<input name="txt" type="text" value={this.state.txt} onChange={this.handleChange}></input>


//根据表单元素类型获取值
const value = target.type === "checkbox"
  ? target.checked
  : target.value

//根据name设置对应state
this.setState({
  [name]: value
})

construction(){
  super()
  this.txtRef = React.reacteRef()
}
<input type="text" ref={this.txtRef} />
console.log(this.txtRef.current.value)

16.组件的props

// 2.接收数据
const Hello = (props) => {
    console.log(props)
    props.fn()
    // 修改props的值:错误演示!!!!!!!
    // props.name = '123'
    return(
        <div>
            <h1>props:{props.name}</h1>
            {props.tag}
        </div>
    )
}
// 1.传递数据
ReactDOM.render(<Hello name="jack" age={19} fn={()=>console.log('这是一个函数')} tag={<p>这是一个p标签</p>} />,document.getElementById('root'))
// 2.接收数据
class Hello extends React.Component{
    constructor(props){
        super(props)
        console.log(props)
        props.fn()
    }
    render(){
        return(
            <div>
                <h1>props:{this.props.age}</h1>
            </div>
        )
    }
}
// 1.传递数据
ReactDOM.render(<Hello name="rose" age={19} color={['red','green','blue']}  />,document.getElementById('root'))
class Hello extends React.Component{
//推荐将props传递给父类构=构造函数
  constrauctor(props){
    super(props)
  }
  render(){
    return (
             <div>
                 <h1>props:{this.props.age}</h1>
             </div>
    )
  }
}

子传父

const { Provider, Consumer } = React.createContext()
<Provider value="pink">
<Consumer>
  { data => <span>data参数表示接收到的数据 -- { data }</span> }
</Consumer>

18.props深入
18.1 children属性:表示组件标签的子节点,当组件标签有子节点时,props就会有该属性

function Hello (props){
  return(
    <div>
      组件的子节点:{ props.chihldren }
    </div>
  )
}

< Hello>我是子节点</Hello>

18.2 props校验:允许在创建组件的时候,就指定props的类型、格式等

App.propTypes = {
  colors: PropTypes.array
}

使用步骤:

import PropTypes from 'prop-types'
//添加props校验
//属性a的类型 数值
//属性fn的类型 函数并且为必填项
//属性tag的类型 React元素(element)
//属性filter的类型 对象({area: '上海', price: 1999})
App,propTypes = {
  a: Proptypes.number,
  fn: Proptypes.func.isRequired,
  tag: Proptypes.element,
  filter: Proptypes.shape({
    area: Proptypes.string,
    price: Proptypes.number
  })
}

18.3 props默认值:未传入props时生效
App.defaultProps = {
pageSize:0
}

  1. 组件的生命周期
    19.1 意义:组件的生命周期有助于理解组件的运行方式,完成更复杂的组件功能,分析组件错误原因等
    组件的生命周期:组件从被创建到挂载到页面中运行,再到组件不用卸载的过程
    生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数
    钩子函数 的作用:为开发人员在不同阶段操作组件提供了时机
    只有 类组件 才有生命周期
    19.2 生命周期的三个阶段
    生命周期.jpg
//比较更新前后的props是否相同,来决定是否重新渲染组件
if(prevProps.count !== this.props.count){
  this.setState({})
  //或者发送ajax请求的代码
}
  1. render-props和高阶组件
    20.1 React组件复用
    复用什么:1.state 2. 操作state的方法(组件状态逻辑)
    两种方式:1.render props模式 2. 高阶组件(HOC)
//调用
<Mouse render={(mouse)  =>{
... ...
}}></Mouse>

//组件内部
render(){
  return this.props.render(this.state)
}

children代替render属性

//调用
<Mouse>{() => {
... ...
}}<Mouse>

//组件内部
this.props.children(this.state)

组件优化:

//添加校验
Mouse.propsTypes = {
  children: PropTypes.func.isRequired
}

代码优化:
1.给render props模式添加props校验
2.应该在组件卸载时,解除mousemove事件绑定

Mouse.propsTypes = {
  children: PropTypes.func.isRequired
}

componentWillUnmount(){
  window.removeEventListener('mousemove',this.handleMouseMove)
}

20.2高阶组件
目的:实现状态逻辑复用
使用步骤:
1.创建一个函数,名称约定以with开头
2.指定函数参数,参数应该以大写字母开头(作为要渲染的组件)
3在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
4.在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件
5.调用改高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中

function withMouse(WrappedComponent){
  class Mouse extends React.Component {}
  return Mouse
}

//Mouse组件中的render方法
return <WrappedComponent {...this.state} />
//创建高阶组件
function withMouse(WrappedComponent){
  //该组件提供复用的状态逻辑
  class Mouse extends React.Component{
    state:{
      x:0,
      y:0
    }

    handleMouseMove = e => {
      this.setState({
        x:e.clientX,
        y:e.clientY
      })
    }

    //  控制鼠标状态的逻辑
    componentDidMount(){
      window.addEventListener('mousemove',this.handleMouseMove)
    }
    componentWillUnmount(){
      window.removeEventListener('mousemove',this.handleMouseMove)
    }

    render(){
      return <WrappedComponent {...this.state} {...this.props} />
    }
  }
  //设置displayName
  Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`

  return Mouse
}

function getDisplayName(WrappedComponent){
  return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}

//用来测试高阶组件
const Position = props =>{
   return (
      <p>
        鼠标当前位置:(x:{props.x},y:{props.y})
      </p>
  )

}

//获取增强后的组件:
const MousePosition = withMouse(Position)

class App extends React.Component{
  render() {
     return(
      <div>
        <h1>高阶组件</h1>
        <MousePosition a='1' />
      <div/>
    )
  }
}

设置displayName

Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`

function getDisplayName(WrappedComponent){
  return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}

传props:

    render(){
      return <WrappedComponent {...this.state} {...this.props} />
    }
    //组件MousePosition 传入的参数就不会丢失了

21.setState说明
21.1异步更新
调用多次setState,只会触发一次render渲染
21.2推荐语法

this.setState((state,props)=>{
  return{
    count:state.count + 1
  }
})

回调函数形式的setState更新也是异步更新,立刻打印state,结果还是1。
连续两次更新state加1,第二次是在第一次基础上加一的,即第二次拿到的值是2,第二次更新是在2上➕1
21.3
setState第二个参数

this.setState(
(state,props)=>{},
()=>{console.log('这个回调函数会在状态跟新后立即执行')}
)
上一篇 下一篇

猜你喜欢

热点阅读