一、使用构造函数创建组件
开始创建
- 组件名必须大写
//The tag <hello> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
- 组件必须向外return一个合法的JSX创建的虚拟DOM
- 父组件可以向子组件传递数据,在组件标签中使用
属性名=data
的方式 - 子组件接收外界传递的数据,需要在组件构造函数的参数列表中使用
props
,其他命名也可 - 使用这种方式,
props
对象的属性,是组件标签中的属性名
import React from 'react'
import ReactDOM from 'react-dom'
//第一种创建组件的方式
//直接将组件名称当做HTML标签
//像虚拟DOM对象,放到ReactDOM.render函数中使用
//在构造函数中,使用 props形参,接收外界传递来的数据
function Hello(props){
//如果 组件返回null,则表示空,无渲染
//return null
//在Vue和React中,props是只读的,不能重新赋值
//props.name = 'new书'
//Uncaught TypeError: Cannot add property name, object is not extensible
console.log(props)//{bookName: "书", boolTitle: "javascript", bookTag: "react"}
//在组件中,必须返回一个合法的JSX虚拟DOM元素
return <div>这是 Hello 组件 --{props.bookName}</div>
}
const book = {
name: '书',
title: 'javascript',
tag: 'react'
}
ReactDOM.render(
//使用组件,并为组件传递 props 数据
<Hello bookName={book.name} boolTitle={book.title} bookTag={book.tag}></Hello>
, document.getElementById('app'))
使用 展开运算符...
向子组件传递数据
此时props对象的属性没有变化;本质上还是使用了属性名=data
的形式,因为直接{book}
是错误的
function Hello(props){
console.log(props)//{name: "书", title: "javascript", tag: "react"}
return <div>这是 Hello 组件 --{props.bookName}</div>
}
ReactDOM.render(
<Hello {...book}></Hello>
, document.getElementById('app'))
向子组件直接传递对象
此时,book成为了props对象的属性
react组件的虚拟DOM中不能存在对象 props.book
需要是用{props.book.name}
获得数据
function Hello(props){
console.log(props)//{book: {…}}
//return <div>这是 Hello 组件 --{props.book}</div>
//Uncaught Error: Objects are not valid as a React child
return <div>这是 Hello 组件 --{props.book.name}</div>
}
ReactDOM.render(
<Hello book={book}></Hello>
, document.getElementById('app'))
将组件抽离为单独的JSX文件
确保web.config.js
配置中test: /\.js|jsx$/
有匹配JSX文件,让babel去解释
创建文件:src->components->Hello.jsx
import React from 'react' //必须
//创建即导出
export default function Hello(props){
console.log(props)
return <div>这是Hello组件</div>
}
//将组件导出,两种导出方式不可以同时使用
//export default Hello
使用自定义组件
import React from 'react'
import ReactDOM from 'react-dom'
//导入 Hello 组件
//默认,如果未单独配置,不能省略.jsx后缀
import Hello from './Components/Hello.jsx'
const book = {
name: '书',
title: 'javascript',
tag: 'react'
}
ReactDOM.render(<Hello {...book}></Hello>, document.getElementById('app'))
省略引用组件的后缀名,配置webpack.json.js
,重启服务生效
module.exports = {
resolve: {
//表示以下下扩展名可以自动补全
extensions:['.js','.jsx','json']
}
}
使用@
符号表示根目录下的src
路径
resolve: {
//表示以下扩展名可以自动补全
extensions: ['.js', '.jsx', 'json'],
//配置别名
alias: {
'@': path.join(__dirname, './src')
}
}
二、使用class创建组件
在class关键字创建的组建中,通过this.props.xxx
直接使用父组件传递的数据,不用接受参数
import React,{Component} from 'react'
import ReactDOM from 'react-dom'
class Hello extends React.Component{
//组件内部必须有render函数
//必须return JSX虚拟DOM结构
render (){
console.log(this.props)
return <div>这是一个Hello组件--{this.props.name}</div>
}
}
const book = {
name: 'ES6',
title: 'javascript'
}
ReactDOM.render(
<Hello {...book}></Hello>
, document.getElementById('app'))
为组件添加私有数据
class Hello extends React.Component{
constructor(){
super()
//这个this.state相当于Vue中的data(){return {}}
this.state = {
msg: '这是Hello组件的私有数据'
}
}
//组件内部必须有render函数
//必须return JSX虚拟DOM结构
render (){
console.log(this.props)
return <div>这是一个Hello组件--{this.props.name}--
{this.state.msg}</div>
}
}
两种组件的异同
- 两种组件的本质区别:有无state属性,和有无生命周期
有状态组件:
使用class关键字创建的组件,有自己的私有数据(this.state)和生命明周期;运行效率低;使用率高;无状态组件:
用function创建的组件,只有props,没有自己的私有数据和生命周期;运行效率高;使用率低;- 两种组件创建的组件,props都是只读的