开始学习React啦(一)

218 阅读3分钟

一、JSX

在学习react之前,我们必须先了解什么是JSX,实质就是JavaScript +XML 的一个扩展语法,有以下的特点:

  • 可以作为值使用

  • 不是字符串

  • 不是HTML

  • 可以配合JavaScript 表达式一起使用

  • 对大小写敏感,标签名用小写,组件用大写

  • 所有标签都必须闭合

const div = <div className="main">
          <header>
              <h1>欢迎进入 React 的世界</h1>
              <p>没有 JSX 的 <br />React 世界是黑暗的</p>
          </header>
      </div>;

为了有效的防止 XSS 注入攻击,React DOM 会在渲染的时候把内容(字符串)进行转义,所以字符串形式的标签是不会作为 HTML 标签进行处理的

二、Render

使用 React 构建视图,构建的是一个虚拟DOM(纯对象),JSX就是虚拟DOM的语法糖

在我们平时日常写的JSX中,会通过React.createElement进行一个代码转义

其用法如下:

React.createElement(type,props,children1,....childrenN)

  • 返回值:构建好的虚拟DOM

  • type 类型(标签名|组件名)

  • props null|{} 元素对应的属性

  • children 子节点(包括文本节点)

最终虚拟DOM还是需要渲染真实DOM的,这时候我们就需要了解下RenctDom.render

其用法如下:

ReactDOM.render(VDOM,container,[callback]):将构建好的虚拟DOM,渲染成真实DOM

  • VDOM 要构建的视图

  • container 挂载节点(容器,将构建好的视图放在哪个真实元素中)

  • callback 可选参数, 真实 DOM 渲染完的回调函数

function App() {
  return (
    <div className="App">
      stydy react
    </div>
  );
}


ReactDOM.render(
    <App />,
  document.getElementById('root')
);

三、插值表达式

React中,插值表达式通过一对大括号{}使用,可以接受一个javascript表达式

表达式有什么?

  • 各种运算符

  • 函数调用

  • 变量或常量

而在插值表达式中,表达式的计算结果必须为 ReactElement

那什么是ReactElement?

  • React 构建的虚拟DOM

  • string | number 会 原样输出

  • boolean | null | undefined 会被忽略为空

  • 数组:去掉连接符后进行输出,有几位就输出几个子节点

  • 注释{/*内容*/}

  • 函数会被忽略

四、类组件

组件类必须继承 React.Component,同时必须有render方法

可以设置state属性存放组件的状态(类似vuedata属性),当组件状态有修改时,会对组件进行更新,从而完成组件的视图更新

修改组件的状态是通过组件的setState方法完成

基本用法如下:

this,setState(updater, [callback])

updater是用于更新数据,可以是Function或者Object

callback为更新成功后的回调函数

react 通常会集齐一批需要更新的组件,然后一次性更新来保证渲染的性能,因此setState方法是一个异步的方法

state = {
    x : 0
}

this.setState(x+1)
this.setState(x+2)
this.setState(x+3)

this.state.x // 3

如果想要使用更新后的state进行操作,我们可以在setState回调函数中编写

state = {
    x : 0
}

this.setState(x+1,() => {
    console.log(this.state.x) // 1
})
console.log(this.state.x) // 0

setState采取的是浅合并的策略

state = {
    x : 0,
    y : 1
}

this.setState({  
    x : 1
})
// 不会覆盖state中y的值

上述例子有点类似Object.assign

this.state = Object.assign(this.state,{x:1})

注意:直接通过this.state.xxx='xxx'这种形式修改数据,并不会使页面视图完成更新

关于事件绑定,我们尤其需要关注this的指向问题

<button onClick={this.handlerClick}>递增</button>

建议使用箭头函数的方式进行事件的声明

handlerClick = ()=>{
    // ...
}

也可以在constructor中对事件进行绑定(不推荐)

constructor{
    this.handlerClick = this.handlerClick.bind(this)
}

完整示例代码

import {Component} from "react";

class App extends Component {
  state = { // 类似于 Vue 中的 data 属性
    count: 1
  }
  handlerClick = ()=>{
    const {count} = this.state;
    this.setState({
      count: count + 1
    });
  }
  render(){
    const {count} = this.state;
    return <div>
        <p>{count}</p>
        <button onClick={this.handlerClick}>递增</button>
    </div>
  }
}

五、列表渲染

通过数组的map方法,需要为每个成员设置key值,用于diff算法更高效比较

const data = {
    a:{
        title: "列表-1"
    },
    b:{
        title: "列表-2"
    },
    c:{
        title: "列表-3"
    }
}
const dataArr = Object.keys(data).map((item,index)=><li key=						{index}>{data[item].title}</li>);
const list = <ul>{dataArr}</ul>;

六、条件输出

在插槽表达式中使用if关键字

const fn=(nub)=>{
  if(nub < 5){
      return "小于5";
  }
  if(nub < 10){
    return "小于10";
  }
  if(nub < 20){
    return "小于20";
  } 
  return "大于等于20"
}
const div = <div>
  <div>左侧不成立||返回右侧 - {2<0||"不成立"}</div>
  <div>左侧成立&&返回右侧 - {2>0&&"成立"}</div>
  <div>条件?成立:不成立 - {2<0?"成立":"不成立"}</div>
  <div>{fn(20)}</div>
</div>;