react-单向数据流

594 阅读3分钟

React 单向数据流 和 状态提升

  • 单向数据流

  • 状态提升

  • 主要思想是:组件不能修改接收的数据

  • 父组件中的数据改变了,子组件就会接受到新的数据。但是反过来,子组件不能修改接收到的 props 数据。因此,数据流动方向是:父组件 -> 子组件

  • 状态提升:在 React 中,状态分享是通过将 state 提升至离需要这些数据的组件最近的父组件来完成的,这就是所谓的状态提升

  • 开发模式:父组件提供数据(状态),子组件从父组件中获取数据,并进行展示处理

组件通讯

  • 父 -> 子:props

  • 子 -> 父:父组件通过 props 传递回调函数给子组件,子组件调用函数将数据作为参数传递给父组件

  • 兄弟组件:因为 React 是单向数据流,因此需要借助父组件进行传递,通过父组件回调函数改变兄弟组件的 props

  • React 中的状态管理: flux(提出状态管理的思想)/ Redux 推荐 / Mobx / ...

  • Vue 中的状态管理: Vuex

  • 简单来说,就是统一管理了项目中所有的数据,让数据变的可控

vue 技术栈:vue + vue-router + vuex + axios react 技术栈:react + react 路由 + redux + axios/fetch

Context 特性

  • 注意:如果不熟悉 React 中的数据流,不推荐使用这个属性
  • 作用:共享全局数据,实现组件之间的数据共享,而不必通过组件树的每个层级显式地传递 props
  • 文档
// 创建一个 theme Context,  默认 theme 的值为 light
const ThemeContext = React.createContext('green')

function Child(props) {
  // Child 组件从 context 接收 theme
  return (
    <ThemeContext.Consumer>
      {theme => (
        <button {...props} style={{ color: theme }}>
          颜色主题 {theme}
        </button>
      )}
    </ThemeContext.Consumer>
  )
}

// 中间组件
function Father(props) {
  return (
    <div>
      <Child />
    </div>
  )
}

class Grandfather extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value="red">
        <Father />
      </ThemeContext.Provider>
    )
  }
}

props 校验

  • 作用:通过类型检查,提高程序的稳定性
  • 命令:npm i -S prop-types
  • 类型校验文档
  • 使用:给类提供一个静态属性 propTypes(对象),来约束props
// 引入模块
import PropTypes from 'prop-types'

// ...以下代码是类的静态属性:
// propTypes 静态属性的名称是固定的!!!
static propTypes = {
  initCount: PropTypes.number, // 规定属性的类型
  initAge: PropTypes.number.isRequired // 规定属性的类型,且规定为必传字段
}

受控组件

在 React 中,可变的状态通常保存在组件的state中,并且只能用 setState() 方法进行更新.
我们通过使 react 变成一种单一数据源的状态来结合二者。 React 负责渲染表单的组件仍然控制用户后续输入时所发生的变化。相应的,其值由 React 控制的输入表单元素称为“受控组件”。

  • 在 React 应用中,任何可变数据应该只有一个:“单一数据源”
  • 注意:只能通过 setState 来设置受控组件的值
// 模拟实现文本框数据的双向绑定
;<input type="text" value={this.state.msg} onChange={this.handleTextChange} />

// 当文本框内容改变的时候,触发这个事件,重新给state赋值
handleTextChange = event => {
  console.log(event.target.value)

  this.setState({
    msg: event.target.value
  })
}

评论列表案例

;[
  { name: '小明', content: '沙发!!!' },
  { name: '小红', content: '小明,居然是你' },
  { name: '小刚', content: '小明,放学你别走!!!' }
]