React的初步

77 阅读5分钟

介绍

  • react是有facebook公司的前端开发团队进行开发和维护的一套js库
  • react一切皆组件,all in JS
  • react是用来构建web用户交互界面
  • react提供一套虚拟DOM(virtual dom),机制
  • react中facebook专为其提供一套语法糖---jsx

优点:

  • 一切皆组件,在react中几乎全是使用组件进行开发
  • 速度快,react提供了虚拟dom机制,
  • 跨浏览器兼容,甚至在IE8中也可以使用
  • 单向数据流,适合开发复杂的项目,出了问题容易溯源

缺点

  • react本身不是一套完整的框架,react需要结合flux和redux等架构来实现完整的项目
  • react最多只能算mvc中的view

react解决的痛点

  • 组件化: 在react中一切组件组件
  • 开发效率:react中使用组件化思想,使代码变得易于读懂和开发
  • 运行效率:react采用的是虚拟dom机制,相比于原生开发效率速度更高
  • 可维护:react中使用组件来构建大型项目,使得一些复杂的项目变得易于维护,.
  • 在用户体验方面:react采用SPA(单页面应用),使得用户体验更好.

下载安装

  • 方式一
<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>
  • 方式二
npm i create-react-app -g 全局安装工具链
create-react-app -V  查看版本
create-react-app 项目名称  创建项目
cd xxx  进入项目目录
npm start  开启项目
​
// 修改默认端口号
node_modules/react-scripts/scripts/start.js
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 5000;
或者
`"start": "set port=5000 && react-scripts start"`

项目目录介绍

my-app
    -node_modules   #项目的依赖包
    -public         #公共资源文件
        index.html  #项目唯一的一个页面
    -src            #项目目录
        App.css     #根组件的样式
        App.js      #根组件
        App.test.js #根组件的测试文件
        index.css   #唯一的入口文件的样式
        index.js    #唯一的入口文件
     .gitignore     #上传到Git上忽略的内容
     package-lock.json #安装node_modules 中的依赖包的锁定版本
     package.json   #安装node_modules中相关的依赖项
     READ.me        #项目解读文件

JSX语法:JSX是对js的扩充,允许js和html混写

  1. 遇到 <>,JSX 就解析成 HTML;遇到 {}按 JavaScript 解析。
  2. 虚拟 DOM 只允许有一个根节点
  3. JSX 标签可以相互嵌套注意换行和缩进,增强代码的可读性
  4. 建议使用小括号括将 JSX 代码括起来 ,防止分号自动插入的 bug
  5. 通过 JSX 语法将数据绑定到虚拟 DOM 对象(是一个js的object),再通过 render 将数据渲染到真实 DOM

修改标签内容

内容可以有简单的运算,类似vue的文本插值

修改标签属性

  <img src={imgUrl} alt="" />
  <a href={url} >你好</a>
  {/* 在jsx的语法中,html的类名class要写成className,js中的class还写成class */}
  <div className={className1}>修改我的class</div>
  {/* 在jsx的语法中,style的类型需要是对象,所以需要两个花括号。多个单词的属性名要写成:fontSize */}
  <div style={{ color: 'red', fontSize: '40px' }}>修改我的style</div>

条件渲染

  <div>条件渲染:简单的用三元表达式写,复杂的用if...else</div>
  <div>
    {
      (function () {
        if (hasWude) {
          return (<p>666</p>)
        } else {
          return (<p>555</p>)
        }
      })()
    }
  </div>

循环渲染

  <div>循环渲染,类似vue的v-for。使用map方法实现</div>
  <ul>
    {
      list.map(item => {
        return (<li key={item.name}>{item.name}---{item.age}</li>)
      })
    }
  </ul>

组件

函数组件和类组件的区别:1.比较熟悉function,不熟悉class,class功能更强大,function性能更好;2.class可以有this;3.class有生命周期钩子,函数组件没有;4.state的处理。函数组件适用于简单的静态页面展示。

事件绑定

  • 两种绑定方式
  <button onClick={(e) => this.showData('ES6', e)}>ES6-箭头函数</button>
  {/* 默认this是undefined,需要通过bind(this)绑定 */}
  <button onClick={this.showData.bind(this, 'ES5')}>ES5-普通函数</button>
  {/* <button onClick={this.showData}>ES5-普通函数</button> */}
  • 传递参数
  {/* this指向当前组件,参数在e前面 */}
  <button onClick={(e) => this.showData('ES6', e)}>ES6-箭头函数</button>
  {/* 默认this是undefined,需要通过bind(this)绑定,参数在this后面 */}
  <button onClick={this.showData.bind(this, 'ES5')}>ES5-普通函数</button>
  {/* <button onClick={this.showData}>ES5-普通函数</button> */}
  • 事件对象

    传递事件对象e之后,可以获取e相关的信息,例如e.target.value等

  • 阻止默认事件

    e.preventDefault(); (写return false不行)

  • 阻止冒泡

    e.stopPropagation()

  • 改为捕获的方式

    加上Capture这个关键字,例如:onClickCapture={(e)=>this.clickHandler1('big',e)}

state 状态机:管理数据状态,可以初始化数据,类似vue中的data

  1. 初始化
  this.state = {
    age: 18,
    money: 1000,
    msg: ''
  }
  1. 获取状态:this.state.xxx
  2. 修改状态,这是一个异步的方式,想要获取最新的值,可以在回调函数中获取
  this.setState({
    money: this.state.money + 100
  }, ()=> {
    console.log(this.state.money);
  })

props的使用

在组件中通过this.props.xx获取,如果想在构造函数中使用props,需要传入参数

constructor(props){
  // 调用super之后,才可以使用this
  super(props);
  // state:状态机。管理数据状态,可以初始化数据,类似vue中的data
  this.state = {
    age: 18,
    val: this.props.val // 使用props中的值进行初始化
  }
}
render() {
  console.log(this.props);
  // 在其他函数中可以通过解构赋值获取
  const {age,name} = this.props
  return (
      <div className="alert alert-info" >
          <h1>用户信息</h1>
          <div>name的值为:{name}</div>
          <div>age的值为:{age}</div>
      </div>
  )
}

通过props实现组件传值:

  1. 父传子:通过组件的属性传递
      // 在父组件中
      <ComC
        info={this.state.msg}
        info2="2"
      ></ComC>
      // 在子组件中
      render(props) {
        return (
          <div>
            <mark>{this.state.msg}</mark>
            {/* 子组件通过this.props接受父组件的数据 */}
            <h1>{this.props.info}</h1>
            <h1>{JSON.stringify(this.props)}</h1>
            {/* 子组件触发父组件的函数,并在参数的位置传入数据,传给父组件 */}
          </div>
        )
      }
  子组件不能修改父组件传过来的值,read only property,这是只读属性
2. 子传父
  // 父组件传给子组件的函数,函数中包含了获取数据之后的操作
  fn(data) {
    this.setState({
      childMsg: data
    })
  }
  // 在父组件中,先向子组件传递一个函数
  <ComC
    fn={this.fn.bind(this)}
  ></ComC>
  // 在子组件中调用传过来的函数,函数的参数就是子传父的数据
  <button onClick={(e)=>this.props.fn(this.state.msg,e)}>子传父</button>

state和props的区别:

  1. state: 是组件内部的状态数据,state的数据不能直接修改,如果需要修改需要通过特殊方法setState()进行修改.
  2. props:一般用于组件之间通信,并且通常是父组件向子组件传递数据,通过this.props来接收.this.props的数据不能直接修改,如果需要修改,则需要通过父组件中的setState来进行修改.