一、props 了解
理解
1、每个组件对象都会有 props(properties的简写)属性
2、组件标签的所有属性都保存在 props 中
作用
通过标签属性从组件外向组件内传递变化的数据
注意
组件内部不要修改 props 数据
二、案例
需求:自定义用来显示一个人员信息的组件
姓名必须指定,且为字符串类型;
性别为字符串类型,如果性别没有指定,默认为男
年龄为字符串类型,默认为18
1、基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>props基本使用</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 1、创建组件
class Person extends React.Component {
// state是在组件内部定义数据,通过 this.state.xxx 访问
// state = { name: 'jerry', sex: '男', age: '19' }
render() {
console.log(this) // Person组件的实例对象
// 通过Person组件实例的props属性接收外部传入数据
const { name, sex, age } = this.props
return (
<ul>
<li>姓名:{ name }</li>
<li>性别:{ sex }</li>
<li>年龄:{ age }</li>
</ul>
)
}
}
// 2、渲染组件到页面
ReactDOM.render(<Person name="jerry" sex="男" age={19}/>, document.getElementById('test1'))
ReactDOM.render(<Person name="tom" sex="女" age={18}/>, document.getElementById('test2'))
// 模拟api返回数据处理(批量传递属性)
const p = { name: '老刘', sex: '女', age: 18 }
// ReactDOM.render(<Person name={p.name} sex={p.sex} age={p.age}/>, document.getElementById('test3'))
// 简写 (返回数据p中的数据项(name、sex、age...)必须存在,否则取不到值)
ReactDOM.render(<Person {...p}/>, document.getElementById('test3'))
/* ... 展开运算符 */
// <Person {...p}/> 中的 {} 代表要在此处写js表达式,并不是字面量对象
// ... 不能遍历对象,babel+react 允许使用 ... 遍历对象,仅适用于标签属性传递
console.log('展开运算符', ...p)
</script>
</body>
</html>
2、对 props 进行限制
React 中使用 propTypes 对标签属性进行类型、必要性的限制
React.PropTypes 形式 React v15.5 开始已弃用
React v15.5 及以后版本以后引入 prop-types 库,对组件标签属性进行限制
React 中使用 defaultProps 指定默认标签属性值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对props进行限制</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制,全局有PropTypes对象 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
class Person extends React.Component {
render () {
const { name, sex, age } = this.props
// this.props.speak() // 执行传入方法
// props是只读的
// this.props.name = 'jack' // 此行代码会报错,因为props是只读的
return (
<ul>
<li>姓名:{ name }</li>
<li>性别:{ sex }</li>
<li>年龄:{ age + 1 }</li>
</ul>
)
}
}
// 伪代码
Person.属性规则 = {
name: '必传,字符串',
sex: '非必传,字符串,默认男',
age: '非必传,数字,默认18'
}
// React 中使用 propTypes 对标签属性进行类型、必要性的限制
Person.propTypes = {
// name: React.PropTypes.string.isRequired, // React v15.5 开始已弃用
name: PropTypes.string.isRequired, // 限制name必传,且为字符串
sex: PropTypes.string, // 限制sex为字符串
age: PropTypes.number, // 限制age为数字
speak: PropTypes.func // 限制speak为函数(function会和关键字冲突,改为使用func)
}
// React 中使用 defaultProps 指定默认标签属性值
Person.defaultProps = {
sex: '男', // sex默认值为男
age: 18 // age默认值为18
}
ReactDOM.render(<Person name="jerry" speak={speak}/>, document.getElementById('test1'))
ReactDOM.render(<Person name="tom" sex="女" age={18} speak={speak}/>, document.getElementById('test2'))
// 给实例传入方法,限制传入方法必须为函数
function speak() {
console.log('我说话了')
}
</script>
</body>
</html>
3、props 的简写方式
使用 static 关键字,给类自身添加属性;将 propTypes、defaultProps 写在类中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对props进行限制</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
class Person extends React.Component {
constructor(props) {
// 构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
// console.log(props)
super(props)
console.log('constructor', this.props)
}
/* 简化写法:使用static关键字,给类自身添加属性 */
// 对标签属性进行类型、必要性的限制
static propTypes = {
name: PropTypes.string.isRequired, // 限制name必传,且为字符串
sex: PropTypes.string, // 限制sex为字符串
age: PropTypes.number, // 限制age为数字
}
// 指定标签默认属性值
static defaultProps = {
sex: '男', // sex默认值为男
age: 18 // age默认值为18
}
render() {
const { name, sex, age } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age + 1}</li>
</ul>
)
}
}
ReactDOM.render(<Person name="jerry" />, document.getElementById('test'))
</script>
</body>
</html>
4、函数组件使用 props
函数式组件,可以通过接收参数形式使用 props;props 会收集所有传递的标签属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对props进行限制</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
function Person(props) {
const { name, age, sex } = props
return (
<ul>
<li>姓名:{ name }</li>
<li>性别:{ sex }</li>
<li>年龄:{ age }</li>
</ul>
)
}
// React 中使用 propTypes 对标签属性进行类型、必要性的限制
Person.propTypes = {
name: PropTypes.string.isRequired, // 限制name必传,且为字符串
sex: PropTypes.string, // 限制sex为字符串
age: PropTypes.number, // 限制age为数字
}
// React 中使用 defaultProps 指定标签默认属性值
Person.defaultProps = {
sex: '男', // sex默认值为男
age: 18 // age默认值为18
}
ReactDOM.render(<Person name="jerry" />, document.getElementById('test'))
</script>
</body>
</html>
三、展开运算符了解
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<script type="text/javascript">
let arr1 = [1, 3, 5, 7, 9]
/* 1、展开一个数组 */
console.log(...arr1) // 1 3 5 7 9
/* 2、连接数组 */
let arr2 = [2, 4, 6, 8, 10]
let arr3 = [...arr1, ...arr2]
console.log(arr3) // [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
/* 3、不定参数(在函数中使用) */
function sum(...numbers) {
return numbers.reduce((preValue, currentValue) => {
return preValue + currentValue
})
}
console.log(sum(1, 2, 3, 4)) // 10
/* 4、构造字面量对象时使用展开语法 */
let person = { name: 'tom', age: 18 }
// 4.1、深拷贝一层
let person2 = { ...person }
person.name = 'jerry'
console.log(person) // {name: 'jerry', age: 18}
console.log(person2) // {name: 'tom', age: 18}
// console.log(...person) // 报错,展开运算符不能展开对象
// 4.2、合并
let person3 = { ...person, name: 'jack', address: '地球' }
console.log(person3) // {name: 'jack', age: 18, address: '地球'}
</script>
</body>
</html>