React 基础小知识:props

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

二倍速刷 B 站 # 尚硅谷2021版React技术全家桶 视频,记录一下有趣的一些点吧。(习惯看文章和看文档,现刷视频感觉有点不适应,单口相声老师讲的很好,讲的太细但也不错。)

props 概念

props:属性,是一个 JavaScript 对象。

  • props 是调用方传递给组件的数据(类似于函数的形参),而 state 是在组件内被组件自己管理的数据(类似于在一个函数内声明的变量)。
  • props 是不可修改的,所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。 由于 props 是传入的,并且它们不能更改,因此我们可以将任何仅使用 propsReact 组件视为 pureComponent,也就是说,在相同的输入下,它将始终呈现相同的输出。
class Person extends React.Component {
  render() {
    const { name, age, sex } = this.props;
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性别:{sex}</li>
        <li>年龄:{age}</li>
      </ul>
    );
  }
}
ReactDOM.render(<Person name="jerry" age="19" sex="男" />, document.getElementById("test1"));
ReactDOM.render(<Person name="tom" age="18" sex="女" />, document.getElementById("test2"));
ReactDOM.render(<Person name="sophia" age="24" sex="女" />, document.getElementById("test3"));
复制代码

回顾三点运算符

let arr1 = [1, 3, 5, 7, 9];
let arr2 = [2, 4, 6, 8, 10];
console.log('展开数组', ...arr1); // 展开数组
let arr3 = [arr1, arr2]; // 数组合并
console.log('数组合并', arr3);
let copyArr = [...arr1]; // 数组复制
console.log('数组复制', copyArr);

// 函数实参
function log(x, y, z) {
   console.log('函数实参', x, y, z)
}
let args = [1, 1, 1, 1, 1];
log(...args);

// 函数行参
function sum(...numbers) {
  return numbers.reduce((pre, cur) => {
    return pre + cur;
  })
}
console.log('函数行参', sum(1, 2, 3, 4));

let obj1 = {a: 1, b: 2};
let obj2 = {c: 3, d: 4};
let obj3 = {...obj1, ...obj2}; // 对象合并
console.log('对象合并', obj3);
let copyObj = {...obj1}; // 对象复制
console.log('对象复制', copyObj);

let person = {name: 'tom', aget: '18'};
console.log('对象展开', ...person); // 对象展开失败
复制代码

截屏2021-10-11 下午3.57.38.png

上面这段代码介绍了三点运算符大部分用法:展开数组、数组合并、数组复制、对象合并、对象复制、函数实参、函数形参...

但是经过试验发现对象展开失败,可以看出直接写展开运算符展开对象是无法成功的,需要在外面包一层花括号复制该对象。所以:三点运算符无法直接遍历一个对象,但是三点运算符可以直接遍历一个数组并以一串字符的形式输出。

批量传递 props

当我们需要批量传递 props 时,可以使用到三点运算符去实现:

const p = {name: 'sophia', age: 24, sex: '女'}

ReactDOM.render(<Person {...p} />, document.getElementById("test"));
复制代码

但是要注意的是 <Person {...p} /> 中的 {...p} 不等同于上一章节提到的对象展开失败的用法。React 渲染函数中的花括号是作为分隔符在使用,而真正写的 JS 只有 ...p

但是我们上面不是提到三点运算符无法直接遍历一个对象 吗?实际上 React + Babel 可以允许展开运算符在标签属性传递这里展开一个对象,但是原生 JS 是不可以的。

对 props 进行限制

// 引入 prop-types 包:通过 PropTypes 调用
class Person extends React.Component {
  // 对标签属性进行类型和必要性的限制
  static propTypes = {
    name: PropTypes.string.isRequired,
    sex: PropTypes.string,
    age: PropTypes.number,
    speak: PropTypes.func, // 由于 function 是关键字,所以内置类型为 func
  }
  
  // 指定默认标签属性值
  static defaultProps = {
    sex: '女',
    age: 24
  }

  render() {
    const { name, age, sex } = this.props;
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性别:{sex}</li>
        <li>年龄:{age}</li>
      </ul>
    );
  }
}

const p = {name: 'sophia', age: 24, sex: '女'}
ReactDOM.render(<Person {...p} />, document.getElementById("test"));

ReactDOM.render(<Person name="jerry" age={19} speak={speak} />, document.getElementById("test1"));
ReactDOM.render(<Person name="tom" age={18} sex="女" />, document.getElementById("test2"));
ReactDOM.render(<Person name="sophia" age={24} sex="女" />, document.getElementById("test3"));
复制代码

其实对 props 的限制原本可以使用 Person.propTypesPerson.defaultProps 在 Person 类的外部进行定义,但是由 React 基础小知识:类可以知道直接将属性赋值到类上的方式其实就是类的静态属性,因此可以使用 static 关键字进行定义。

构造器中的 props

首先我们要知道构造器有什么作用?

截屏2021-10-11 下午9.05.57.png

在官网上已经明确了构造器的两个作用,不过上面两种情况我们都可以用更方便的方式进行替代:

  • 直接在类里 state = {isHot: false} 进行初始化状态。
  • 直接在类里通过赋值语句配合箭头函数 changeWeather = () => {...} 实现自定义方法。

因此构造器其实可以省略

super(props) 的作用是什么?

截屏2021-10-11 下午9.12.18.png

class Person extends React.Component {
  constructor(props) {
    super(props)
    console.log(this.props) // 输出定义属性
    console.log(this.props) // this 可以省略
  }
  
  // constructor() {
  //   super()
  //   console.log(this.props) // undefined
  // }
}
复制代码

通过上面例子可以证明,构造器是否接收 props,是否传递给 super,取决于是否希望在构造器中通过 this 访问 props。

如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。

其实在开发中很少需要自定义构造器,因此能不写就可以不写。

函数式组件使用 props

组件实例三大属性:state、props、refs,因为类式组件中的实例拥有 this,所以可以通过 this 访问 state、props、refs。

对于函数式组件来说,它没有 this,因此也就无法使用 state、refs,但是依然可以使用 props,因为函数可以接收参数。

function Person (props) {
  const { name, age, sex } = props;
  return (
    <ul>
      <li>姓名:{name}</li>
      <li>性别:{sex}</li>
      <li>年龄:{age}</li>
    </ul>
  );
}


const p = {name: 'sophia', age: 24, sex: '女'}
ReactDOM.render(<Person {...p} />, document.getElementById("test"));

ReactDOM.render(<Person name="jerry" age={19} speak={speak} />, document.getElementById("test1"));
ReactDOM.render(<Person name="tom" age={18} sex="女" />, document.getElementById("test2"));
ReactDOM.render(<Person name="sophia" age={24} sex="女" />, document.getElementById("test3"));
复制代码

猜你喜欢

转载自juejin.im/post/7018088547185852430