React 学习入门

发布于 2022-03-29 12:39:21 字数 7126 浏览 1101 评论 0

React 的创建是为了数据的频繁交互:通过组件化轻松展现数据;数据改变时,自动更新 UI,并且只更新有改变的部分。

组件入门

创建组件

var component = React.createClass()用来创建一个组件类,组件类似于函数,可以把它看作有着 props 和 state 状态并且可以返回(render())HTML 结构的函数。

React.render()将 React 的模板转化为 HTML,并插入到相应的 DOM 结构中,React.render方法可以渲染 HTML 结构,也可以渲染 React 组件。

渲染 HTML 标签

声明变量采用首字母小写

var myDivElement = <div className="foo" />
React.render(myDivElement, document.body)

渲染 React 组件

声明变量采用首字母大写

var MyComponent = React.createClass({
  /*...*/
})
var myElement = <MyComponent someProperty={true} />
React.render(myElement, document.body)

关于 JSX

目的

组件应该关注分离,而不是模板和展现逻辑分离。结构化标记和生成结构化标记的代码是紧密关联的,此外,展现逻辑一般都很复杂,使用模板语言会使展现变得笨重。

语法说明

标签的属性 class 和 for,需要写成 className 和 htmlFor,因为两个属性是 JavaScript 的保留字和关键字,无论你是否使用 JSX。

JSX 是 HTML 和 JavaScript 混写的语法,当遇到<,JSX 就当 HTML 解析,遇到{就当 JavaScript 解析。

虚拟 DOM

React 使用了内部的虚拟 DOM,当数据发生改变,先在虚拟 DOM 中计算变化,最后将变动的部分反应到真实的 DOM 中。

#app.js
var HelloWorld = React.createClass({
    render: function () {
        return (
            <p>
            Hello,<input type="text" placeholder="Your name here" value={this.props.date.toTimeString()}/>!
            It is {this.props.date.toTimeString()}
            </p>
        );
    }
});

setInterval(function () {
    React.render(
        <HelloWorld date={new Date()} />,
        document.getElementById('example')
    );
}, 500);

input 相对于这个组件来说,是它的属性,并且没有嵌入动态的数据。而在 React 的设定中,属性是不可变的。

组件属性

属性延伸

例如 component 组件有两个动态的属性 foo 和 bar:

var component = <Component foo={x} bar={y} />;

而实际上,有些属性可能是后续添加的,当需要拓展我们的属性的时候,定义个一个属性对象,并通过{...props}的方式引入,React 会帮我们拷贝到组件的 props 属性中。

可以使用属性延伸覆盖原来的属性值:

var Component = React.createClass({
  render: function () {
    return (
      <div {...this.props} title="zzz">
        this is a div
      </div>
    )
  },
})

React.render(<Component name="xxx" title="yyy" />, document.body)

style 属性

在 React 中写行内样式时,要这样写,不能采用引号的书写方式

React.render(<div style={{ color: 'red' }}>xxxxx</div>, document.body)

UI 交互

this.props

var HelloWorld = React.createClass({
  render: function () {
    return <div data-title={this.props.title}>{this.props.content}</div>
  },
})

React.render(<HelloWorld title="this is title" content="this is content" />, document.body)

通过this.props我们可以拿到组件被使用时的属性,this.props 就是组件的属性集合。React 将组件的子节点封装到了 children 属性中,当子节点只有一个的时候直接通过this.props.children获取子节点的内容。当子节点的个数大于 1 时,this.props.children返回的是一个数组。

this.state

this.state是同 UI 交互最重要的属性,this 指向组件的实例。React 将 UI 简单的看作状态机,拥有各种各样的状态,并在各种状态间切换,这样很容易保持 UI 的一致性。在 React 中,你只要改变组件的状态,就会重新渲染 UI,React 会在最有效的方式下更新 DOM。通过调用setState(data, callback)方法,改变状态,就会触发 React 更新 UI。

var ColorButton = React.createClass({
  getInitialState: function () {
    return { bColor: 'green' }
  },
  render: function () {
    return (
      <button onClick={this.handleClick} style={{ backgroundColor: this.state.bColor }}>
        click
      </button>
    )
  },
  // 点击按钮,切换按钮的颜色:
  handleClick: function (event) {
    this.setState({ bColor: this.state.bColor === 'green' ? 'red' : 'green' })
  },
})

React.render(<ColorButton />, document.body)

getInitialState是用来初始化 state,handleClick是用来处理我们点击事件的,如果想要拿到当前操作的 DOM,通过参数 event 获取。

两种属性的运用

大部分的组件应该从 props 属性中获取数据并渲染。但有的时候组件得相应用户输入,同服务器交互,这些情况下会用到 state。React 的官方说法是:尽可能的保持你的组件无状态化。为了实现这个目标,得保持你的状态同业务逻辑分离,并减少冗余信息,尽可能保持组件的单一职责。

React 官方推荐的一种模式就是:构建几个无状态的组件用来渲染数据,在这些之上构建一个有状态的组件同用户和服务交互,数据通过 props 传递给无状态的组件。

var RenderComponent = React.createClass({
  render: function () {
    return (
      <ul>
        {this.props['data-list'].map(function (item) {
          return <li>{item}</li>
        })}
      </ul>
    )
  },
})

var StateComponent = React.createClass({
  getInitialState: function () {
    return { list: ['xxx', 'yyy'] }
  },
  render: function () {
    return (
      <div>
        <button onClick={this.handleClick}>click</button>
        <RenderComponent data-list={this.state.list} />
      </div>
    )
  },
  handleClick: function () {
    this.setState({ list: [1, 2, 3] })
  },
})

React.render(<StateComponent />, document.body)

React 还允许我们下面的方式自定义属性的默认值:

var ComponentWithDefaultProps = React.createClass({
  getDefaultProps: function () {
    return {
      value: 'default value',
    }
  },
  /* ... */
})

getDefaultProps()的值将会被缓存,当this.props.value的值没有被父组件指定时,将会使用这个默认值。

组件组合

官方示例:

var Avatar = React.createClass({
  render: function () {
    return (
      <div>
        <ProfilePic username={this.props.username} />
        <ProfileLink username={this.props.username} />
      </div>
    )
  },
})

var ProfilePic = React.createClass({
  render: function () {
    return <img src={'http://graph.facebook.com/' + this.props.username + '/picture'} />
  },
})

var ProfileLink = React.createClass({
  render: function () {
    return <a href={'http://www.facebook.com/' + this.props.username}>{this.props.username}</a>
  },
})

React.render(<Avatar username="pwh" />, document.getElementById('example'))

上面的例子中,组件 Avatar 包含了组件 ProfilePic 和 ProfileLink。在 React 当中,所有者就是可以设置其他组件 props 的组件。说的通俗点:如果组件 X 出现在了组件 Y 的 render()方法中,那么组件 Y 就是所有者。正如我们之前所讨论的,组件不能改变 props—props 应同所有者初始化它们时保持一致。

父子节点的关系

一定要弄清所有者和被所有关系,父子关系的区别。所有者和被所有者关系是针对 React 组件的,父子关系是针对 DOM 结构的。来上面的例子来说,Avatar 是所有者,拥有 div、ProfilePic、ProfileLink,而 div 和 ProfilePic、ProfileLink 则是父子关系。

<Parent><Child /></Parent>创建实例,Parent 可以通过 this.props.children 获取到它的子内容。

动态子节点

在 React 更新 DOM 的过程中,子节点是根据它们渲染的顺序调节的。实际上,React 改变第一个子节点的内容,然后删除最后一个节点。所以当数据来自于搜索结果或者新的组件被添加到数据流里,在这种情况下,每个子节点都需要保持唯一的标识,此时可以给每个子节点添加 key 属性。

var Component = React.createClass({
  render: function () {
    var results = this.props.results
    return (
      <ol>
        {results.map(function (result) {
          return <li key={result.id}>{result.text}</li>
        })}
      </ol>
    )
  },
})

单向数据流

在 React 当中,数据通过 props 从所有者向子节点传递,这就是所谓的单向数据绑定了。所有者将它拥有的组件 props 绑定到它的 props 或者 state,这个过程将会递归进行。数据改变就会通过组件到子组件再到子节点即所有的 DOM 节点,最终反映到 UI 层。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

文章
评论
84963 人气
更多

推荐作者

夢野间

文章 0 评论 0

doggiejohn

文章 0 评论 0

就此别过

文章 0 评论 0

初见终念

文章 0 评论 0

qq_rvKjBH

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文