侧边栏壁纸
博主头像
woku博主等级

成功的路上并不拥挤

  • 累计撰写 50 篇文章
  • 累计创建 13 个标签
  • 累计收到 3 条评论

组件与props

woku
2022-04-21 / 0 评论 / 0 点赞 / 149 阅读 / 4,522 字

什么是组件

  • 组件视图的片段
  • 组件表示页面中的部分功能
  • 多个组件可以实现完整的页面功能
  • 组件特点:可复用,独立,可组合

包含:视图标记,事件,数据,逻辑,外部的配置
组件中的state : 内部管理数据的集合
组件中的props:外部传入的配置集合

类组件接收props

class Test extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      title: 'this is a class Component'
    }
  }
  handleClick() {
    this.setState({
      title: 'this is my Component'
    })
  }
  render() {
    return (
      <div>
        <h1>{ this.state.title }</h1>
        <button onClick={this.handleClick.bind(this)}>change</button>
      </div>
    )
  }
}
ReactDOM.render(<Test />, document.getElementById('app'))

state表示组件Test内部自己的数据
使用Test组件传入一些配置props,类组件接收props

class Test extends React.Component {
  constructor(props) {
    super(props)
    console.log(props)
    // { title: "this is a class Component" }
    this.state = {
      title: this.props.title
    }
  }
  handleClick() {
    this.setState({
      title: 'this is my Component'
    })
  }
  render() {
    return (
      <div>
        <h1>{ this.state.title }</h1>
        <button onClick={this.handleClick.bind(this)}>change</button>
      </div>
    )
  }
}
ReactDOM.render(<Test title="this is a class Component" />, document.getElementById('app'))

this.props中保存着所有用户传入的配置项

函数组件接收props

函数组件直接在参数中就可以接收到props

function Test(props) {
  const [title, setTitle] = React.useState(props.title)
  return (
    <div>
      <h1>{ title }</h1>
      <button onClick={() => setTitle('this is my Component')}>change</button>
    </div>
  )
}
// ReactDOM.render(React.createElement(Test, {
//   title: 'this is a class Component'
// }), document.getElementById('app'))
ReactDOM.render(<Test title="this is a class Component" />, document.getElementById('app'))

组件渲染的过程

  1. React主动调用Test组件
  2. 将属性集合转换成props对象
  3. 将对象作为props传入组件
  4. 替换JSX中的props或者state变量
  5. ReactDOM将React元素经过一系列操作转成真实DOM进行渲染

组件调用规范

  • 组件标记是HTML标签,可以直接写HTML标签,如
  • 大驼峰写法调用JSX组件
  • 组件转换成React元素(JSX、React.createElement())
ReactDOM.render(React.createElement(Test, { title: 'this is a class Component' }), document.getElementById('app'))

组合组件

一个组件由多个子组件组成

class Title extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    return (
      <h2>{ this.props.title }</h2>
    )
  }
}
class Author extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    return (
      <span>{ this.props.author }</span>
    )
  }
}
class Para extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    return (
      <p>{ this.props.para }</p>
    )
  }
}
class App extends React.Component {
  constructor(props) {
    super(props)
  }
  state = {
    title: 'this is a title',
    author: 'woku',
    para: 'this is a para'
  }
  render() {
    return (
      <div>
        <Title title={ this.state.title }/>
        <Author author={ this.state.author }/>
        <Para para={ this.state.para } />
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('app'))

组件嵌套

一个组件中嵌套着其他组件

class Title extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    const { title, author, para } = this.props
    return (
      <div>
        <h2>{ title }</h2>
        <Author author={ author }/>
        <Para para={ para } />
      </div>
    )
  }
}
class Author extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    return (
      <span>{ this.props.author }</span>
    )
  }
}
class Para extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    return (
      <p>{ this.props.para }</p>
    )
  }
}
class App extends React.Component {
  constructor(props) {
    super(props)
  }
  state = {
    title: 'this is a title',
    author: 'woku',
    para: 'this is a para'
  }
  render() {
    return (
      <div>
        <Title title={ this.state.title }
        author={ this.state.author }
        para={ this.state.para }
        />
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('app'))

state和props区别

用途读写性
state数据池(组件内部管理数据容器)可读可写
props属性池(外部调用组件传入配置集合)只可读,不可写
class App extends React.Component {
  constructor(props) {
    super(props)
  }
  handleClick() {
    this.props.content = '123'
  }
  render() {
    return (
      <div>
        <h2>{ this.props.content }</h2>
        <button onClick={this.handleClick.bind(this)}>点击</button>
      </div>
    )
  }
}
ReactDOM.render(<App content="this is a content"/>, document.getElementById('app'))

在点击按钮的时候,修改props属性,会直接报错:
Uncaught TypeError: Cannot assign to read only property 'content' of object '#'

如何才能修改呢?
我们可以修改state自己内部的数据,可以给state增加一个content数据,默认值为外部传入的配置,修改的时候直接修改内部state

class App extends React.Component {
  constructor(props) {
    super(props)
  }
  state = {
    // 这里喔!
    content: this.props.content
  }
  handleClick() {
    this.setState({
      content: '123'
    })
  }
  render() {
    return (
      <div>
        <h2>{ this.state.content }</h2>
        <button onClick={this.handleClick.bind(this)}>点击</button>
      </div>
    )
  }
}
ReactDOM.render(<App content="this is a content"/>, document.getElementById('app'))

💡 函数组件一定是一个纯函数,保证绝对的复用性

  1. 相同的入参返回相同的结果
  2. 不可以修改入参
function test(a, b) {
  return a + b
}
// 是纯函数
function test(a, b) {
  a = a + 1
  return a + b
}
// 不是纯函数

从设计上来说,在函数内部更改入参,其实是在组件运行时更改外部的配置
那么配置的意义就丧失了
用户好不容易把配置传进来,结果你函数内部把我的配置给改了。
所以,不管是类组件还是函数组件,都不可以改变props(只读不可写)

0

评论区