React(04):React中的组件化及父子组件间的传值取值

前言

接着前一篇继续学习React组件化
React(03):React中的JSX语法

正文

什么是组件化: 是从 UI 界面视图的角度 来进行分析的;把一些可复用的UI元素,抽离为单独的组件;便于项目的维护和开发;

React认为一个组件应该具有以下特征:

  • 可组合(Composeable):一个组件易于和其他组件一起使用,或者嵌套在另一个组件内部。如果一个组件内部创建了另一个组件,那么说父组件用于(own)他创建的子组件,通过这个特性,一个复杂的UI可以拆分成多个简单的UI组件;
  • 可重用(Reusable):每个组件都是具有独立功能的,它可以被使用在多个UI场景;
  • 可维护(Maintainable):每个小的组件仅仅包含自身的逻辑,更容易被理解和维护;

React允许将代码封装成组件(Component),然后像插入普通HTML标签一样,在网页中插入这个组件。

一、React创建与引用组件

1.1 单个组件

  • 使用function创建函数式组件
function Hello(props) {
    return <h1>这是 Hello 组件 --- {props.name} --- {props.age} </h1>
}
ReactDOM.render(
    <Hello name="小明" age="28"/>,,
    document.getElementById('example')
)

特点:它是为了创建纯展示组件,这种组件只负责根据传入的props来展示,不涉及到state状态的操作,组件不能访问this对象,不能访问生命周期方法;

  • 使用class创建组件
class HelloMsg extends React.Component {
    render() {
        return <h1>组件测试,父组件传值={this.props.name}</h1>
    }
}
ReactDOM.render(
    <HelloMsg name="小明" />,
    document.getElementById('example')
)

特点:用class创建的组件有状态,组件能访问this对象,可以访问生命周期方法;

1.2 多个组件组合

function Hello(props) {
    return <h1>这是 Hello 组件 --- {props.name} --- {props.age} </h1>
}

class HelloMsg extends React.Component {
    render() {
        return <h1>class组件测试,父组件传值={this.props.name}</h1>
    }
}
function App(){
  return(
    <div> 
      <Hello name="小明" age="28"/>
      <HelloMsg name="小红" age="18"/>
      <Hello name="小新" age="08"/>
    </div>
  )
}
ReactDOM.render(
  <App/>,
  document.getElementById('example3')
)

1.3 两种创造组件的区别

  • 用构造函数创建的组件没有状态。
  • 用class创建的组件有状态。
  • 两种组件的本质的区别为state属性。State 与 props 类似,但是 state 是私有的,并且完全受控于当前组件。

案例:demo03

二、组件之间的传值

先来个案例,从案例中分析组件之间的传值:


<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="js/react.development.js">script>
    <script src="js/react-dom.development.js">script>
    <script src="js/babel.min.js">script>
    <title>组件之间的传值title>
head>

<body>
    <div id="example">div>
    <script type="text/babel">
        // 函数
        function Hello(props) {
            return (
                <div>
                    <div>这是 Hello 函数组件 --- {props.name} --- {props.age}</div>
                    <p>我还想拿到HelloMsg组件的值: {props.helloMsg || '还没有传递过来'}</p>
                     父组件给的函数:{props.handleSignUp()}
                </div>
            )
        }
        // class
        class HelloMsg extends React.Component {
            constructor(props) {
                super(props);
                this.state = {
                    msg: '子组件的消息',
                    name: '李小黑',
                    age: 100,
                    helloMsg:'啦啦啦,你好啊'
                };
            }
            handleChange=()=>{
                this.props.changeMsg(this.state)
            }
            render() {
                return (
                    <div>
                        <p>这是HelloMsg组件,父组件传来的值--{this.props.data.msg}: 我爸爸是:{this.props.data.name}--他今年{this.props.data.age}</p>
                        <button onClick={this.handleChange}>点击子组件更改父组件参数,年龄去增加</button>
                        {this.props.handleSignUp()}
                    </div>
                )
            }
        }
        class App extends React.Component {
            constructor(props) {
                super(props);
                // 改变内部thisde指向
                this.handleSignUp = this.handleSignUp.bind(this);
                this.state = {
                    msg: '内部消息',
                    name: 'Jcat_李小黑',
                    age: 88,
                };
            }
           // 改变内部thisde指向
            changeMsg=(child)=>{
                // setState方法,修改msg的值,值是由child里面传过来的,单项数据流
                this.setState({age:child.age++});
                this.setState({helloChildMsg:child.helloMsg});
            }
            handleSignUp() {
                console.log(`你好, ${this.state.name}!`);
                return ( 
                    <h1>你好, {this.state.name}</h1>
                )
            }
            render() {
                return (
                    <div className="app">
                        {this.handleSignUp()}
                        <hr/>
                        <p>这里是父组件的页面,我是{this.state.name},拥有的消息是:{this.state.msg}</p>
                        <p><b>我今年:{this.state.age}</b></p>
                        <p>子组件HelloMsg给我的信息:{this.state.helloChildMsg || '还没有传递过来'}</p>
                        <hr/>
                        <HelloMsg data={this.state} handleSignUp={this.handleSignUp} changeMsg={this.changeMsg} />
                        <hr/>
                        <Hello handleSignUp={this.handleSignUp} name={this.state.name} age={this.state.age} helloMsg={this.state.helloChildMsg}/>
                    </div>
                )
            }
        }
        ReactDOM.render(
            <App />,
            document.getElementById('example')
        )
    script>
body>

html>

案例分析:

  • 父组件:App
  • class子组件:HelloMsg
  • 函数式子组件:Hello

首先要知道React的组件间通讯是单向的。
数组必须是由父级传到子级或者子级传递给父级层层传递。
如果要给兄弟级的组件传递数据,那么就要先传递给父级而后在传递给你要传递到的组件位置。

2.1 父组件给子组件传值

传递参数

  • App组件向子组件传值时,父组件将参数传递在标签上;
render() {
    return (
        <div className="app">
            <HelloMsg data={this.state}  />
            <Hello name={this.state.name} age={this.state.age} helloMsg={this.state.helloChildMsg}/>
        </div>
    )
}
  • 构造函数组件HelloMsg,需要在构造函数的参数列表中使用props,{this.props.data.msg}来接收;
render() {
    return (
        <div>
            <p>这是HelloMsg组件,父组件传来的值--{this.props.data.msg}: 我爸爸是:{this.props.data.name}--他今年{this.props.data.age}</p>
        </div>
    )
}
  • 函数式组件Hello中使用形参props来接收;
function Hello(props) {
    return (
        <div>
            <div>这是 Hello 函数组件 --- {props.name} --- {props.age}</div>
        </div>
    )
}

传递函数方法

  • App父组件传递函数,写到标签上:
render() {
    return (
        <div className="app">
            <HelloMsg  handleSignUp={this.handleSignUp} />
            <Hello handleSignUp={this.handleSignUp}/>
        </div>
    )
}
  • 构造函数组件HelloMsg也是使用this.props.handleSignUp()接收
render() {
    return (
        <div>
            {this.props.handleSignUp()}
        </div>
    )
}
  • 函数式组件Hello,没有状态,也没有生命周期,所以只能接收,不能改变函数值,使用形参props来接收;
function Hello(props) {
    return (
        <div>
             父组件给的函数:{props.handleSignUp()}
        </div>
    )
}

小结

  1. 父组件将参数传递写在标签上,子组件都是使用props接收参数;
  2. props只能接收参数,不能修改参数,修改参数要接收到值后使用setState去修改;
  3. class函数内部this指向问题,需要改变this的指向;
// 方法1:es6的写法
handleChange=()=>{
    this.props.changeMsg(this.state)
}
// 方法2: 使用bind 改变内部this指向
constructor(props) {
    super(props);
    this.handleSignUp = this.handleSignUp.bind(this);
}
// 方法3: 在调用的时候使用箭头函数调用
class Test extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={() => this.handleClick()}>
        点击
      </button>
    );
  }
}

2.2 子组件向父组件之间的传值

  1. 在父组件内设置修改参数的函数
changeMsg=(child)=>{
    // setState方法,修改msg的值,值是由child里面传过来的,单项数据流
    this.setState({age:child.age++});
    this.setState({helloChildMsg:child.helloMsg});
}
  1. 子组件接收方法,并生成函数;
handleChange=()=>{
    this.props.changeMsg(this.state)
}
  1. 子组件内部调用方法
render() {
    return (
        <div>
            <button onClick={this.handleChange}>点击子组件更改父组件参数,年龄去增加</button>
        </div>
    )
}
  1. 父组件接收变动的参数
render() {
    return (
        <div>
            <p>子组件HelloMsg给我的信息:{this.state.helloChildMsg || '还没有传递过来'}</p>
        </div>
    )
}

2.2 同级别的组件间传值

  • 采用props传值

    上述代码中的helloChildMsg
    HelloMsg组件传给App组件,App组件再传给Hello组件,这种方式比较麻烦;

  • 使用全局状态管理Redux (单开文章去讲)

三、其他注意事项

  1. 组件名称必须以大写字母开头。
  2. 不论是 Vue 还是 React,组件中的 props 永远都是只读的;不能被重新赋值。
  3. Fragment,如果你不想让你的组件最外层有标签包裹的话可以使用Fragment将你的组件包裹起来,它不会渲染。
  4. 组件只能包含一个根节点。
  5. 尽量使用函数式组件,保持简洁和无状态。
  6. 必须要向外return一个合法的JSX创建的虚拟DOM。

结语

以上就是React中组件化及组件之间的传值;

其他博文请移步React专栏

如果本文对你有帮助的话,请不要忘记给我点赞打call哦~o( ̄▽ ̄)do
有问题留言 over~

你可能感兴趣的:(React)