从零开始学习react系列(一)

311 阅读4分钟

Hello React

react的优点起源简介不再介绍,看文档

react开发依赖

开发react必须依赖三个库

  • react --包含react所需核心代码
  • react-dom --react渲染在不同平台需要的代码
  • babel --将jsx转成react代码的工具 #####如何添加这三个依赖 方式1:直接CDN引入
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

方式2:通过npm管理

###开始hello world

  • 先创建一个helloworld.html文件
<div id="app"></div>

  <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

  <script type="text/babel">
    // 通过ReactDom对象来渲染内容
    ReactDOM.render(<h2>Hello World</h2>, document.getElementById("app"));
  </script>
  • 上面的代码解析
  • ReactDOM.render函数:
  • 这里我们已经提前定义一个id为app的div
  • 这里我们传入了一个h2元素,后面我们就会使用React组件
  • 参数一:传递要渲染的内容,这个内容可以是HTML元素,也可以是React的组件
  • 参数二:将渲染的内容,挂载到哪一个HTML元素上 ###类组件 ReactDOM.render 第一参数是一个HTML原生或者一个组件。
class App extends React.Component {
  render() {
    return (<h2>Hello World</h2>)
  }
}

ReactDOM.render(<App/>, document.getElementById("app"));

#####数据在哪里定义

  • 在组件中的数据,我们可以分成两类:

    • 参与界面更新的数据:当数据变量时,需要更新组件渲染的内容
    • 不参与界面更新的数据:当数据变量时,不需要更新将组建渲染的内容
  • 参与界面更新的数据我们也可以称之为是参与数据流,这个数据是定义在当前对象的state中

  • 我们可以通过在构造函数中 this.state = {定义的数据}

  • 当我们的数据发生变化时,我们可以调用 this.setState 来更新数据,并且通知React进行update操作

  • 在进行update操作时,就会重新调用render函数,并且使用最新的数据,来渲染界面 #####事件绑定中的this

  • 在类中直接定义一个函数,并且将这个函数绑定到html原生的onClick事件上,当前这个函数的this指向的是谁呢?

  • 默认情况下是undefined

  • 很奇怪,居然是undefined;

    • 因为在正常的DOM操作中,监听点击,监听函数中的this其实是节点对象(比如说是button对象);
    • 这次因为React并不是直接渲染成真实的DOM,我们所编写的button只是一个语法糖,它的本质React的Element对象;
    • 那么在这里发生监听的时候,react给我们的函数绑定的this,默认情况下就是一个undefined;
  • 我们在绑定的函数中,可能想要使用当前对象,比如执行 this.setState 函数,就必须拿到当前对象的this

  • 我们就需要在传入函数时,给这个函数直接绑定this

    • 类似于下面的写法:
<button onClick={this.changeText.bind(this)}>改变文本</button>
class App extends React.Component {
  constructor() {
    super();
    this.state = {
      message: "Hello World"
    };
  }

  render() {
    return (
      <div>
        <h2>{this.state.message}</h2>
        <button onClick={this.changeText.bind(this)}>改变文本</button>
     </div>
    )
  }

  changeText() {
    this.setState({
      message: "Hello React"
    })
  }
}

ReactDOM.render(<App/>, document.getElementById("app"));

###JSX语法

jsx表达式

  • 书写规则:{表达式}
  • 大括号内可以是变量、字符串、数组、函数调用等任意js表达式;

jsx注释

<div>
  {/* 我是一段注释 */}
  <h2>Hello World</h2>
</div>

jsx嵌入变量

  • 情况一:当变量是Number、String、Array类型时,可以直接显示

  • 情况二:当变量是null、undefined、Boolean类型时,内容为空;

    • 如果希望可以显示null、undefined、Boolean,那么需要转成字符串;
    • 转换的方式有很多,比如toString方法、和空字符串拼接,String(变量)等方式;
  • 情况三:对象类型不能作为子元素(not valid as a React child)

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      name: "why",
      age: 18,
      hobbies: ["篮球", "唱跳", "rap"],
      
      test1: null,
      test2: undefined,
      flag: false,

      friend: {
        name: "kobe",
        age: 40
      }
    }
  }

  render() {
    return (
      <div>
        {/* 我是一段注释 */}
        <h2>Hello World</h2>
      </div>

      <div>
        {/* 1.可以直接显示 */}
        <h2>{this.state.name}</h2>
        <h2>{this.state.age}</h2>
        <h2>{this.state.hobbies}</h2>

        
        {/* 2.不显示 */}
        <h2>{this.state.test1}</h2>
        <h2>{this.state.test1 + ""}</h2>
        <h2>{this.state.test2}</h2>
        <h2>{this.state.test2 + ""}</h2>
        <h2>{this.state.flag}</h2>
        <h2>{this.state.flag + ""}</h2>
        
        {/* 3.不显示 */}
        <h2>123{this.state.friend}</h2>
      </div>
    )
  }
}

ReactDOM.render(<App/>, document.getElementById("app"));

jsx嵌入表达式

{/* 运算表达式 */}
        <h2>{this.state.firstName + " " + this.state.lastName}</h2>
        {/* 三元运算符 */}
        <h2>{this.state.age >= 18 ? "成年人": "未成年人"}</h2>
        {/* 执行一个函数 */}
        <h2>{this.sayHello("kobe")}</h2>

jsx属性绑定

 <h2 title={this.state.title}>Hello World</h2>
        <img src={this.state.imgUrl} alt=""/>
        <a href={this.state.link} target="_blank">百度一下</a>
        <div className={"message " + (this.state.active ? "active": "")}>你好啊</div>
        <div className={["message", (this.state.active ? "active": "")].join(" ")}>你好啊</div>
        <div style={{fontSize: "30px", color: "red", backgroundColor: "blue"}}>我是文本</div>

jsx事件监听

class App extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.btnClick}>点我一下(React)</button>
      </div>
    )
  }

  btnClick() {
    console.log("React按钮点击了一下")
  }
}
this绑定问题
  • 默认下this是undefined

  • 为什么是undefined?

原因是btnClick函数并不是我们主动调用的,而且当button发生改变时,React内部调用了btnClick函数;

而它内部调用时,并不知道要如何绑定正确的this;

如何解决this绑定
  • 方案一:bind给btnClick显示绑定this

    <button onClick={this.btnClick.bind(this)}>点我一下(React)</button>
    
  • 方案二:箭头函数

    class App extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          message: "你好啊,李银河"
        }
      }
    
      render() {
        return (
          <div>
            <button onClick={this.btnClick}>点我一下(React)</button>
            <button onClick={this.btnClick}>也点我一下(React)</button>
          </div>
        )
      }
    
      btnClick = () => {
        console.log(this);
        console.log(this.state.message);
      }
    }
    
  • 方案三:事件监听时传入箭头函数(推荐)

    class App extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          message: "你好啊,李银河"
        }
      }
    
      render() {
        return (
          <div>
            <button onClick={() => this.btnClick()}>点我一下(React)</button>
            <button onClick={() => this.btnClick()}>也点我一下(React)</button>
          </div>
        )
      }
    
      btnClick() {
        console.log(this);
        console.log(this.state.message);
      }
    }
    
事件参数传递
  • 获取event对象

    btnClick(e) {
        e.preventDefault();
        console.log(e);
      }
    

条件渲染

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isLogin: true
    }
  }

  render() {
    let titleJsx = null;
    if (this.state.isLogin) {
      titleJsx = <h2>欢迎回来~</h2>
    } else {
      titleJsx = <h2>请先登录~</h2>
    }

    return (
      <div>
        {titleJsx}
      </div>
    )
  }
}

当然,我们也可以将其封装到一个独立的函数中:

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isLogin: true
    }
  }

  render() {
    return (
      <div>
        {this.getTitleJsx()}
      </div>
    )
  }

  getTitleJsx() {
    let titleJsx = null;
    if (this.state.isLogin) {
      titleJsx = <h2>欢迎回来~</h2>
    } else {
      titleJsx = <h2>请先登录~</h2>
    }
    return titleJsx;
  }
}
v-show效果
render() {
    const { isLogin, username } = this.state;
    const nameDisplay = isLogin ? "block": "none";

    return (
      <div>
        <h2 style={{display: nameDisplay}}>{username}</h2>
        <button onClick={e => this.loginBtnClick()}>{isLogin ? "退出": "登录"}</button>
      </div>
    )
  }

#####搜索微信公众号《蜗牛和曼巴的前端进程》与你一起交流学习