React(1)之——React入门

  React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。使用 React 能够将一些简短、独立的代码片断组合成复杂的 UI 界面,这些代码片断被称做“组件”。html

建立react项目

  1. npm install -g create-react-app下载官方的脚手架工具create-react-app。
  2. create-react-app react01建立一个新的名为react01的项目。
  3. 建立好的react项目目录结构以下:


  同Vue很类似,项目有一个入口文件,入口文件中的根组件会渲染到DOM树的根结点root下。

React和ReactDOM

  React和ReactDOM是开发React项目必不可少的两个包。React负责逻辑控制,它用JSX来描述虚拟DOM以及用它的Component类来建立一个组件;而ReactDOM主要负责渲染,将构建好的虚拟DOM渲染成真实DOM到页面上。
  来自官方的示例:这里面还涉及到另外一个问题,JSX是什么?vue

class HelloMessage extends React.Component {
  render() {
    return React.createElement(
      "div",
      null,
      "Hello ",
      this.props.name
    );
  }
}

ReactDOM.render(React.createElement(HelloMessage, { name: "Taylor" }), document.getElementById('hello-example'));
复制代码

  至关于react

class HelloMessage extends React.Component {
  render() {
    return (
      <div> Hello {this.props.name} </div>
    )
  }
}

ReactDOM.render(
  <HelloMessage name="Taylor" />, document.getElementById('hello-example') ) 复制代码

JSX

  JSX形如js和html的混合体,它在react代替常规的js语法。它的优势:1)执行更快,提升执行效率。2)使用咱们更熟悉的html来描述UI,JSX在react转换为js的写法形如:React.createElement("div",null,"Hello ",this.props.name);,写起来很繁琐。3)它是类型安全的,在编译过程当中就能发现错误。
  JSX就是html加上表达式,下面介绍一下一些表达式的写法:npm

import src from './static/img'
sayHi(){
    return 'hello, react'
}
render(){
    const name = 'zhunny'
    const jsx = '<p>jsx</p>'
    return(
        <div>
        {/*注释语法*/}
        {/*表达式*/}
        <h1>{name}</h1>
        <h1>{this.seyHi()}</h1>
        {/*属性的写法*/}
        <img src={src} style={{width:"200px"}}>
        {/*jsx也能够直接当成是表达式*/}
        {jsx}
        {/*只要是js表达式均可以放在{}里面*/}
        <div>
    )
}
复制代码

建立组件的两种形式

  一种是函数类型组件,一种是基于类的组件。数组

//rfc 比较简洁,直接至关于render函数,但hooks的出现使得它们之间没有太大区别
import React from 'react'

export default function CompType() {
  return (
    <div> </div>
  )
}
//rcc 能够在类中使用各类生命周期钩子,在constructor构造函数中初始化state和props
import React, { Component } from 'react'

export default class CompType extends Component {
  render() {
    return (
      <div> </div>
    )
  }
}
复制代码

state和setState

state

  使用组件时,可能会出现一些特别的状态,它们可能会改变所以影响视图的变化,所以咱们须要去维护这些状态。凡是数据与视图有交互的时候,就须要将这些数据维护到状态state中去。state通常在构造函数constructor中初始化。安全

constructor(props) {
    super(props)
    this.state = {
      count:1
    }
 }
复制代码
setState

  而setState是官方提供给咱们用来修改state值的方法,千万不能直接修改state,会报错。使用setState修改state有两种方法,直接修改state对象setState(obj,cb),或者传入一个修改函数setState(fn,cb)。由于state和setState是批量执行的,这样能够提高更新的性能,可是同时它会认为连续相同的操做形如setState(obj,cb)是同样的,只会执行最后一次。这个时候就须要使用第二种修改state的方法。app

componentDidMount () {
  this.setState({
    count: this.state.count + 1
  })
}
复制代码
componentDidMount () {
  this.setState(preState => ({
    count:preState.count + 1
  }))
  this.setState(preState => ({
    count:preState.count + 1
  }))
}

复制代码

props属性传递

  这是一种父组件向子组件传递属性的一种方式,父->子通讯的方法。两种不一样类型的组件在调用props时有差异。函数

//在父组件中 
import { Welcome1, Welcome2 } from './components/CompType'
export default class App extends Component {
    render () {
        return (
            <Welcome1 name="zhunnyWang" />
            <Welcome2 name="zhunnyWang" />
        )
    }
}
复制代码
//在子组件中 
//props传值,两种方式有区别,props是只读的
//单向绑定,严格的单向数据流
export function Welcome1 (props) {
  return (
    <div> Welcome1,{props.name} </div>
  )
}

export class Welcome2 extends React.Component {
  constructor(props){
    super(props)
  }
  render () {
    return (
      <div>Welcome2,{this.props.name}</div>
    )
  }
}
复制代码

条件渲染和列表渲染

  这是在react使用最频繁的两种表达式写法。条件渲染有两种实现方式,一种是使用三元表达式,一种是使用短路逻辑。父组件向子组件传递了一个props为title='goodlist'。列表渲染就是循环的将一个数组中的元素显示在视图上。工具

export class GoodsList extends React.Component {
  constructor(props){
    super(props)
    this.state = {
        goods:[
         {id:1,name:'《你不知道的Javascript》'}
         {id:2,name:'《CSS世界》'}
        ]
    }
  }
  render () {
    const title = this.props.title ? <h1>{this.props.title}</h1> : null
    return (
      <div> {/*条件渲染的第一种方式,三元表达式*/} {title} {/*条件渲染的第二种方式,短路逻辑*/} {this.props.title && <h1>this.props.title</h1>} {/*列表渲染*/} <ul> {this.state.goods.map(good => (<li key={good.id}>{good.name}</li>))} </ul> </div>
    )
  }
}
复制代码

事件处理

  react的事件处理与原生js形似,形如onClick={this.fn}。事件处理函数的声明有两种方式,一种是经过箭头函数,一种是普通函数可是须要在构造函数中绑定this。性能

export class GoodsList extends React.Component {
  constructor(props){
    super(props)
    this.state = {
        goods:[
         {id:1,name:'《你不知道的Javascript》'}
         {id:2,name:'《CSS世界》'}
        ],
        text: ''
    }
    //不用箭头函数就得绑定this
    this.addGood = this.addGood.bind(this)
  }
  textChange = (e) => {
    this.setState({
      text: e.target.value
    })
  }
  addGood () {
    /** * react官方但愿这是一个纯函数 * 更新的数据不是以前的数据,而是一个全新的数据 */
    this.setState(prevState => {
      return {
        goods: [
          ...prevState.goods,
          {
            id: prevState.goods.length + 1,
            name: prevState.text
          }
        ]
      }
    })
  }
  render () {
    return (
      <div> {/*react严格遵循单向数据流,没有数据的双向绑定,所以须要本身来实现*/} <input type="text" text={this.state.text} onChange={this.textChange} /> <button onClick={this.addGood}>添加商品</button> {/*须要在声明的事件处理函数中传入参数时,也须要借用箭头函数来传参*/} <button onClick={() => {this.addToCart(good)}}>添加商品</button> </div> ) } } 复制代码

组件的通讯

  父传子可使用props来传递,上述章节已经给出示例。子传父也须要借助props传递一个回调函数,经过回调函数来触发父组件中的方法,用父组件中的函数来修改子组件中的值。这与vue有很大的差别,react但愿子组件是一个很是单纯的组件,它只有展现功能,全部的操做在父组件中完成。

//父组件 
export class Counter extends React.Component {
  constructor(props){
    super(props)
    this.state = {
        count:1
    }
  }
  add = (value) => {
    this.setState(prevState => {
        count: preState.count + value 
    })
  }
  render () {
    return (
      <div> <Add count={this.state.count} add={this.add}></Add> </div>
    )
  }
}
//子组件
export function Add ({ count, add }) {
    return(
        <div> {count} <button onClick={add(10)}></button> </div>
    )
}
复制代码
状态提高

  摘自官方文档的一段话,当你遇到须要同时获取多个子组件数据,或者两个组件之间须要相互通信的状况时,须要把子组件的 state 数据提高至其共同的父组件当中保存。以后父组件能够经过 props 将状态数据传递到子组件当中。这样应用当中全部组件的状态数据就可以更方便地同步共享了。
  这就是上述所说的子组件是很是单纯的,父组件操做,只将结果传递给子组件,子组件将结果最终展现到视图上。

不变性

  通常来讲,有两种修改数据的方式,第一种是直接修改变量的值,第二种是将新的数据直接替换旧的数据。在React中,官方推荐咱们在修改状态值时使用全新的数据替换旧数据,维持不变性。
第一种:直接修改变量的值:

const name = { firstName:'wang', secondName:'zhunny' }
name.firstName = 'zhou'
复制代码

第二种:全新的数据替换旧的数据:

const name = { firstName:'wang', secondName:'zhunny' }
const newName = {...name, firstName:'zhou'}  
复制代码

  在React中维持不变性有如下几点好处:

  1. 简化复杂的功能。
  2. 跟踪数据的改变,跟踪不可变数据的变化相对来讲就容易多了。若是发现对象变成了一个新对象,那么咱们就能够说对象发生改变了。
  3. 肯定在 React 中什么时候从新渲染,不可变性最主要的优点在于它能够帮助咱们在 React 中建立 pure components。咱们能够很轻松的肯定不可变数据是否发生了改变,从而肯定什么时候对组件进行从新渲染。在生命周期钩子函数 shouldComponentUpdate() 中会构建 pure components 的内容。
  4. 对于数组和对象这样的引用类型,改变它的指向才能触发render函数,对组件从新渲染。
相关文章
相关标签/搜索