React框架快速入门

React快速入门

ReactJS介绍

ReactJS是什么?

  • 1). Facebook开源的一个js库;
  • 2). 一个用于动态构建用户界面的js库;
  • 3). React的特点;
    • Declarative(声明式编码);
    • Component-Based(组件化编码);
    • Learn Once, Write Anywhere(支持客户端与服务器渲染);
    • 高效;
    • 单向数据流;
  • 4). ReactJS官网:http://facebook.github.io/react/
  • 5). Github地址:https://github.com/facebook/react

React高效的原因

  • 1). 虚拟(virtual)DOM, 不总是直接操作DOM,减少页面更新次数;
  • 2). 高效的DOM Diff算法, 最小化页面重绘;

React的几个重要概念

  • 1.模块与组件
    • 模块:
      • 理解: 向外提供特定功能的js程序, 一般就是一个js文件
      • 为什么: js代码越多越复杂了;
      • 作用: 简化js的编写, 阅读, 提高运行效率
    • 组件:
      • 理解: 用来实现特定功能效果的代码集合(html/css/js)
      • 为什么: 一个界面的功能更复杂
      • 作用: 复用, 简化项目编码, 提高运行效率
  • 2.模块化与组件化

    • 模块化:当应用的js都以模块来编写的, 这个应用就是一个模块化的应用;
    • 组件化:当应用是以多组件的方式实现功能, 这样应用就是一个组件化的应用;
  • 声明式编程和命令式编程

    • 声明式编程:只关注做什么, 而不关注怎么做(流程), 类似于填空题,数组中常见声明式方法:map() / forEach() / find() / findIndex();
    • 命令式编程:要关注做什么和怎么做(流程), 类似于问答题;
      var arr = [1, 3, 5, 7]
      // 需求: 得到一个新的数组, 数组中每个元素都比arr中对应的元素大10: [11, 13, 15, 17]
      // 命令式编程
      var arr2 = []
      for(var i =0;i<arr.length;i++) {
          arr2.push(arr[i]+10)
      }
      console.log(arr2)
      // 声明式编程
      var arr3 = arr.map(function(item){
          return item +10
      })
      // 声明式编程是建立命令式编程的基础上

React的使用

与使用有关的理解

  • JSX

    • 1). 理解

      • 全称: JavaScript XML;
      • react定义的一种类似于XML的JS扩展语法: XML+JS;
      • 作用: 用来创建react虚拟DOM(元素)对象;

        var ele = <h1>Hello JSX!</h1>;
        • 注意1: 它不是字符串, 也不是HTML/XML标签
        • 注意2: 它最终产生的就是一个JS对象
    • 2). 编码相关

      • 基本语法规则
        • 遇到 <开头的代码, 以标签的语法解析:html同名标签转换为html同名元素, 其它标签需要特别解析;
        • 遇到以 { 开头的代码,以JS的语法解析:标签中的js代码必须用{}包含;
      • js中直接可以套标签, 但标签要套js需要放在{}中;
      • 在解析显示js数组时, 会自动遍历显示;
      • 把数据的数组转换为标签的数组:

        var liArr = dataArr.map(function(item, index){
                        return <li key={index}>{item}</li>
                    })
      • babel.js的作用

        • 浏览器的js引擎是不能直接解析JSX语法代码的, 需要babel转译为纯JS的代码才能运行
        • 只要用了JSX,都要加上type=”text/babel”, 声明需要babel来处理
    • 3). 注意:

      • 标签必须有结束;
      • 标签的class属性必须改为className属性;
      • 标签的style属性值必须为: {{color:’red’, width:12}};
  • 虚拟DOM

    • 1). React提供了一些API来创建一种 特别 的一般js对象;

      //创建的就是一个简单的虚拟DOM对象
      var element = React.createElement('h1', {id:'myTitle'}, 'hello');
    • 2). 虚拟DOM对象最终都会被React转换为真实的DOM;

    • 3). 我们编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界面;
    • 4).创建虚拟DOM的2种方式:

      • 1). 纯JS(一般不用):

        //  纯JS方式
        const msg = 'I like you';
        const myId = 'atguigu';
        const vDOM1 = React.createElement('h2',{id:myId},msg);
      • 2). JSX方式:

        //  jsx方式创建虚拟dom元素对象
        const vDOM2 = <h3 id={myId.toUpperCase()}>{msg.toLowerCase()}</h3>
    • 5).渲染虚拟DOM(元素)

      • 1). 语法: ReactDOM.render(virtualDOM, containerDOM) :
      • 2). 作用: 将虚拟DOM元素渲染到真实容器DOM中显示
      • 3). 参数说明
        • 参数一: 纯js或jsx创建的虚拟dom对象
        • 参数二: 用来包含虚拟DOM元素的真实dom元素对象(一般是一个div)
          //  渲染到真实的页面中
            ReactDOM.render(vDOM1,document.getElementById('example1'));
            ReactDOM.render(vDOM2,document.getElementById('example2'));

写个Hello world

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>02_JSX_DEMO</title>
</head>
<body>
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>
<hr>

<div id="example1"></div>
<div id="example2"></div>

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>

<script type="text/babel">
  /*
   功能: 动态展示列表数据
   */
  /*
   技术点:
   1). 使用JSX创建虚拟DOM
   2). React能自动遍历显示数组中所有的元素
   3). array.map()的使用
   */
  //数据的数组
  var names = ['Tom2', 'Jack2', 'Bob2'];
  //数据的数组——>标签数组
  var lis = [];
  names.forEach((item,index)=>lis.push(<li key={index}>{item}</li>));
  //创建虚拟的DOM
  const ul=<ul>{lis}</ul>;
//  将虚拟的Dom渲染到页面中的某个DOM元素中
  ReactDOM.render(ul,document.getElementById('example1'))
  const ul2 = <ul>{names.map((name,index)=><li key={index}>{name}</li>)}</ul>
  ReactDOM.render(ul2, document.getElementById('example2'))

</script>
</body>
</html>

React组件

自定义组件

一、定义组件

  • 方式1:工厂(无状态)函数(简单组件,推荐使用);
//  方式一:工厂函数,推荐使用
  function MyComponent() {
  return <h2>工厂函数</h2>
  }
  • 方式2:ES6类语法;
//  方式二:ES6类语法(复杂组件,推荐使用)
class MyComponent2 extends React.Component{
     render(){
         return <h2>ES6的语法</h2>
     }
 }
  • 方式3:ES5老语法(不推荐使用了)
//  方式三:ES5的老语法
const MyComponent3 = React.createClass({
    render(){
        return <h2>EES5老语法(不推荐使用了)</h2>
    }
})

二、渲染组件标签

//语法规则
ReactDOM.render(<MyComponent/>, document.getElementById('example'));
  • 注意:
    • 1). 返回的组件类必须首字母大写;
    • 2). 虚拟DOM元素必须只有一个根元素;
    • 3). 虚拟DOM元素必须有结束标签;
  • ReactDOM.render()渲染组件标签的基本流程:
    • 1). React内部会创建组件实例对象;
    • 2). 得到包含的虚拟DOM并解析为真实DOM;
    • 3). 插入到指定的页面元素内部;
//  二:渲染组件标签
ReactDOM.render(<MyComponent/>,document.getElementById('example1'));
  ReactDOM.render(<MyComponent2/>,document.getElementById('example2'));
  ReactDOM.render(<MyComponent3/>,document.getElementById('example3'));

组件的三大属性

组件的3大属性之一: props属性

  • 1.每个组件对象都会有props(properties的简写)属性;
  • 2.组件标签的所有属性都保存在props中;
  • 3.内部读取某个属性值: this.props.propertyName;
  • 4.作用: 通过标签属性从组件外向组件内传递数据(只读);
  • 5.对props中的属性值进行类型限制和必要性限制;
//  对标签属性进行限制
Person.propTypes = {
     name:React.PropTypes.string.isRequired,
     sex:React.PropTypes.string,
     age:React.PropTypes.number
 }
  • 6.扩展属性: 将对象的所有属性通过props传递
 <Person {...person}/>
 //具体如下:
 ReactDOM.render(<Person {...person}/>,document.getElementById('example'))
  • 7.默认属性值
//  指定属性的默认值
Person.defaultProps = {
     sex:'男',
     age:18
 }
  • 8.组件类的构造函数
constructor (props) {
  super(props)
  console.log(props) // 查看所有属性
}

组件的3大属性之二: refs属性

  • refs属性
    • 1). 组件内的标签都可以定义ref属性来标识自己;
    • 2). 在组件中可以通过this.refs.refName来得到对应的真实DOM对象;
    • 3). 作用: 用于操作指定的ref属性的dom元素对象(表单标签居多);
 <input ref='username'>
 this.refs.username //返回input对象
  • 事件处理
    • 1). 通过onXxx属性指定组件的事件处理函数(注意大小写)
      • React使用的是自定义(合成)事件, 而不是使用的DOM事件;
      • React中的事件是通过委托方式处理的(委托给组件最外层的元素);
    • 2). 通过event.target得到发生事件的DOM元素对象;
<input onFocus={this.handleClick}/>
        handleFocus(event) {
   event.target  //返回input对象
        }
  • 强烈注意

    • 1). 组件内置的方法中的this为组件对象;
    • 2). 在组件中自定义的方法中的this为null;

      • 强制绑定this;

        this.change = this.change.bind(this);
      • 箭头函数(ES6模块化编码时才能使用);

  • 问题: 如何给一个函数强制指定内部的this?

组件的3大属性之三: state属性

  • 1). 组件被称为”状态机”, 通过更新组件的状态值来更新对应的页面显示(重新渲染)
  • 2). 初始化状态:
constructor (props) {
   super(props)
   this.state = {
     stateProp1 : value1,
     stateProp2 : value2
   }
}
  • 3). 读取某个状态值

    this.state.statePropertyName
  • 4). 更新状态—->组件界面更新

    this.setState({
    stateProp1 : value1,
    stateProp2 : value2
    })
  • 5). 问题: 请区别一下组件的props和state属性?

React其他操作

双向绑定

  • React是一个单向数据流
  • 可以自定义双向数据流组件(受控组件),需要通过onChange监听手动实现;
<script type="text/babel">
 class Control extends React.Component{
     constructor(props){
         super(props)
         //初始化状态
         this.state = {
             msg:'ATGUIGU'
         }
         this.handleChange = this.handleChange.bind(this)

     }

     handleChange(event){
         //得到最新的state的值
         const msg=event.target.value;
//          console.log(event.target)
//          console.log(event.target.value)
         //更新状态
         this.setState({msg})
     }
     render(){
         const {msg} = this.state
         return(
             <div>
               <input type="text" value={msg} onChange={this.handleChange}/>
               <p>{msg}</p>
             </div>
         )
     }
 }
 ReactDOM.render(<Control/>,document.getElementById('example'))
</script>

组件生命周期

  • 1.组件的三个生命周期状态:
    - Mount:插入真实 DOM
    - Update:被重新渲染
    - Unmount:被移出真实 DOM
  • 2.React 为每个状态都提供了两种勾子(hook)函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用;
    • componentWillMount();
    • componentDidMount() : 已插入页面真实DOM, 在render之后才会执行;
    • componentWillUpdate(object nextProps, object nextState);
    • componentDidUpdate(object prevProps, object prevState);
    • componentWillUnmount();
  • 3.生命周期流程:

    • 第一次初始化渲染显示: render()

      • constructor(): 创建对象初始化state
      • componentWillMount() : 将要插入回调函数;
      • render() : 用于插入虚拟DOM回调函数;
      • componentDidMount() : 已经插入回调函数;在此方法中启动定时器/绑定监听/发送Ajax请求;
    • 每次更新state: this.setSate()

      • componentWillUpdate() : 将要更新回调函数;
      • render() : 更新(重新渲染);
      • componentDidUpdate() : 已经更新回调;
      • 删除组件
        • ReactDOM.unmountComponentAtNode(div): 移除组件;
        • componentWillUnmount() : 组件将要被移除回调;
  • 3.常用的方法
    • render(): 必须重写, 返回一个自定义的虚拟DOM;
    • constructor(): 初始化状态, 绑定this(可以箭头函数代替);
    • componentDidMount() : 只执行一次, 已经在dom树中, 适合启动/设置一些监听;
  • 4.注意:
    • 一般会在componentDidMount()中: 开启监听, 发送ajax请求;
    • 可以在componentWillUnmount()做一些收尾工作: 停止监听;
    • 生命周期还有一个方法(后面需要时讲): componentWillReceiveProps;
//测试
class MyComponent extends React.Component{
     constructor(props){
         super(props)
         this.state = {
             msg:'这只是一句话而已'
         }
     }
     componentWillMount(){
         console.log('componentWillMount')

         //启动一个定时器,更新状态
         setTimeout(function () {
             this.setState({msg:Date.now()})
         }.bind(this),2000)

         //启动一个定时器,移除组件
         setTimeout(function () {
             ReactDOM.unmountComponentAtNode(document.getElementById('example'))
         },4000)
     }
     render(){
         console.log('render()')
         const {msg}=this.state
         return <p>{msg}</p>
     }
     componentDidMount(){
         console.log('componentDidMount')
     }
     componentWillUpdate () {
         console.log('componentWillUpdate')
     }
     componentDidUpdate () {
         console.log('componentDidUpdate')
     }
     componentWillUnmount () {
         console.log('componentWillUnmount')
     } 
 }
 ReactDOM.render(<MyComponent/>,document.getElementById('example'))

//一个小练习,文字渐隐
class Fade extends React.Component{
    constructor(props){
        super(props)
        this.state={
            opacity:1
        }
    }
    componentDidMount(){
        //在此方法中启动定时器/绑定监听/发送Ajax请求
        this.intervalId=setInterval(function () {
            //保存到当前组件对象中
            let {opacity}=this.state
            //操作当前的数据。
            opacity -= 0.1
            // 更新状态
            this.setState({opacity})
        }.bind(this),500)

    }
    componentWillUnmount(){
        //清除定时器/解除监听
        clearInterval(this.intervalId)
    }
    removeComp(){
        //移除组件
        ReactDOM.unmountComponentAtNode(document.getElementById('example'))
    }
    render(){
        return(
            <div>
              <p style={{opacity:this.state.opacity}}>{this.props.content}</p>
              <button onClick={this.removeComp}>移除组件</button>
            </div>

        )
    }
}

ReactDOM.render(<Fade content={'为什么不过节?'}/>,document.getElementById('example'))

React发送ajax请求

  • 1). React没有ajax模块,所以只能集成其它的js库(如jQuery/axios/fetch), 发送ajax请求;
  • 2). 集成其它的js库(如axios/fetch/jQuery/), 发送ajax请求
    • axios
      • 封装XmlHttpRequest对象的ajax
      • promise
      • 可以用在浏览器端和服务器
    • fetch
      • 不再使用XmlHttpRequest对象提交ajax请求
      • fetch就是用来提交ajax请求的函数, 只是新的浏览才内置了fetch
      • 为了兼容低版本的浏览器, 可以引入fetch.js
  • 3). 在哪个方法去发送ajax请求
    • 只显示一次(请求一次): componentDidMount()
    • 显示多次(请求多次): componentWillReceiveProps()
//做一个跳转页面
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script src="https://cdn.bootcss.com/axios/0.16.2/axios.js"></script>
<script type="text/babel">
class UserLastGist extends React.Component {
    constructor (props) {
        super(props)
        this.state = {
            url: null
        }
    }
    componentDidMount () {
        // 发送ajax请求
        const url = `https://api.github.com/users/${this.props.username}/gists`
        axios.get(url)
            .then(response => {
                console.log(response)
                // 读取响应数据
                //0索引位代表最后更新的网页内容
                const url = response.data[0].html_url
                // 更新状态
                this.setState({url})
            })
            .catch(function (error) {

                console.log('----', error);
            })
    }
    render () {
        const {url} = this.state
        if(!url) {
            return <h2>loading...</h2>
        } else {
            return <p>{this.props.username}'s last gist is <a href={url}>here</a> </p>
        }
    }
}
UserLastGist.propTypes = {
    username: React.PropTypes.string.isRequired
}
ReactDOM.render(<UserLastGist username="octocat"/>, document.getElementById('example'))
</script>

虚拟dom

  • 1). 虚拟DOM是什么?
    • 一个虚拟DOM(元素)是一个一般的js对象, 准确的说是一个对象树(倒立的);
    • 虚拟DOM保存了真实DOM的层次关系和一些基本属性,与真实DOM一一对应;
    • 如果只是更新虚拟DOM, 页面是不会重绘的;
  • 2). Virtual DOM 算法的基本步骤
    • 用JS对象树表示DOM树的结构;然后用这个树构建一个真正的DOM树插到文档当中
    • 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
    • 把差异应用到真实DOM树上,视图就更新了
  • 3). 进一步理解
    • Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。
    • 可以类比 CPU 和硬盘,既然硬盘这么慢,我们就在它们之间加个缓存:既然 DOM 这么慢,我们就在它们 JS 和 DOM 之间加个缓存。CPU(JS)只操作内存(Virtual DOM),最后的时候再把变更写入硬盘(DOM)。

这里写图片描述

猜你喜欢

转载自blog.csdn.net/mutouafangzi/article/details/77688265
今日推荐