龙空技术网

为什么说 React 中 props 是只读的?Angular,Vue中的Props

小焱2018 216

前言:

此时朋友们对“js只读修改”大体比较重视,同学们都需要知道一些“js只读修改”的相关内容。那么小编在网上汇集了一些对于“js只读修改””的相关文章,希望兄弟们能喜欢,朋友们一起来学习一下吧!

React 官方文档说法:

React is pretty flexible but it has a single strict rule: all React components must act like pure functions with respect to their props.

props 是组件的只读属性,组件内部不能直接修改 props,要想修改 props,只能在该组件的上层组件中修改

在 React 中,props 是上层组件传递进来的值,这个值是父类的值,同 Vue 一样,props 的传值是单项数据流,也就是不会让影响父类的值,如果需要改值,可以先让 props 赋值给一个变量,在修改这个变量。

其实就是保证 React 单向数据流的设计模式,使状态可预测。

如果允许子组件修改,那么一个父组件将状态传递给好几个子组件,这几个子组件随意修改,就完全不可预测,不知道在什么地方修改了状态。

一、解决了什么问题?

props是组件(包括函数组件和class组件)间的内置属性,用其可以传递数据给子节点。

二、怎么使用?1、只读

props在传递数据的过程中,是只读得不能修改。

class App extends React.Component {    // 第一步:给节点设置属性 `theme`    render() {        return <Toolbar theme="dark" />;    }}function Toolbar(props) {    // 第二步:子节点可以访问父节点的props属性,但只能读取不能修改    return (        <div>            <ThemedButton theme={props.theme} />        </div>    );}class ThemedButton extends React.Component {    // 第三步:孙子节点依然可访问props属性,同样只能读不能修改     render() {        return <Button theme={this.props.theme} />;    }}
2、{...props}

展开props属性的一种简洁写法,属于 js展开语法 。

var props = { x: 1, y: 1, z:1 };<Component {...props} />// 上面等价于下面的写法<Component x=1 y=1 z=1 />
3、props.children

只见组件的子元素,下面 {props.children} 就是指 : "Hello world!"

<Welcome>Hello world!</Welcome>function Welcome(props) {    return <p>{props.children}</p>;}

对于 class 组件,请使用 this.props.children 来获取:

class Welcome extends React.Component {    render() {        return <p>{this.props.children}</p>;    }}

在React组件开发时,Props是不可以修改的。但Why?如何尽可能确保在实际开发中被修改呢?继续喵

React中关于Props解释

Whether you declare a component as a function or a class, it must never modify its own props.

React is pretty flexible but it has a single strict rule:

All React components must act like pure functions with respect to their props.

结论React类库并没有强制约束不可以修改props,但是规则是不可以修改,是的,这是个Rule函数组件或者类组件都不要修改Props,避免产生副作用举个例子

// App renders a user.name and a profileconst App = (props) =>  React.createElement("div", null, [    props.user.name,    React.createElement(Profile, props)  ]);// Profile changes the user.name and renders it// Now App has the wrong DOM.const Profile = ({ user }) => {  user.name = "Voldemort"; // Uh oh!  return React.createElement("div", null, user.name);};// Render the App and give it propsReactDOM.render(  React.createElement(App, { user: { name: "Hermione" } }),  document.getElementById("app"));

如上,虽然在子组件中我们将user.name进行了修改,但是父组件打印的仍然是Hermione,原因?因为props是个对象,本身并没有修改,React组件更新时的新旧比较时浅对比。

React组件TypeScript定义

class Component<P, S> {       constructor(props: Readonly<P>);       ...

如上可以看出Props是只读参数,这样确保了一定的安全,假如我们直接赋值,会TSC报错

这样就没事了?No,假如参数是个对象类型呢?

如上,不会报错,但是个BUG。根本问题在于当前的Type定义无法确保属性的嵌套属性是只读的。关于这点,其实社区已经有讨论和解决方案,但是当前还没有将新的定义合并进去。

讨论戳这里

当前我们如何确保绝对的不可修改呢?可以将新的定义自己手动放入项目中即可。

Redux Saga中的Select

在组件中,我们使用Redux的值,是以Props形式进行使用,所以仍然应该只读使用。另一种使用场景是在effects中使用const state = yield select();,那么这里的state也应该只读吗?

YES,select实际上就是调用的store.get(key),某个state。注意实际上是个对象,那么假如我们在effects中修改了这个对象,实际上就是修改了单一状态树。因此当我们select拿到状态,注意保持只读性

Angular,Vue中的Props?

Angular,Vue中对于父组件传递过来的参数,并没有明确说明不可以修改,但注意本身在使用方式上都是组件,所以建议也不要修改。

写在最后

理解这些基本的设计规则及理念,有益于使用这些技术,同时对于设计模式也会有帮助。

标签: #js只读修改