React

第1章:React入门

英文官网
中文官网

1.1.React简介

1.1.1.介绍描述
  1. 用于动态构建用户界面的 JavaScript 库(只关注于视图)

  2. 由Facebook开源

实现一个页面需求通常有三步:
1.发送请求获取数据
2.处理数据(过滤、整理格式等)
3.React就是操作DOM呈现页面
是一个将数据渲染为HTML视图的开源 JavaScript 库。

1.1.2.React的特点
  1. 采用组件化模式声明式编码,提高开发效率及组件复用率
    命令式编码:获取节点再改样式;
    声明式编码:用特殊语法表达更改的样式,react会帮我们操作dom
  2. React Native 编写原生应用,进行移动端开发
  3. 使用虚拟DOM+优秀的Diffing 算法,尽量减少与真实DOM交互
1.1.3.React高效的原因
  1. 使用虚拟(virtual)DOM, 不总是直接操作页面真实DOM。
  2. DOM Diffing算法, 最小化页面重绘。

原生JavaScript操作DOM繁琐、效率低(DOM-API操作 UI)
使用JavaScript直接操作DOM,浏览器会进行大量的重绘重排
原生JavaScript没有组件化编码方案,代码复用率低


1.2.React的基本使用

1.2.1.效果

在这里插入图片描述

1.2.2.相关js库
  • react.development.js:React核心库。
  • react-dom.development.js:提供操作DOM的react扩展库。
  • babel.min.js:解析JSX语法代码转为JS代码的库。
    <!--  引入react核心库  -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--  引入react-dom,用于支持react操作DOM  -->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--  引入babel,用于将jsx转为js  -->
    <script type="text/javascript" src="../js/babel.min.js"></script>
1.2.3.创建虚拟DOM的两种方式
  1. 纯JS方式(一般不用)
    在这里插入图片描述

  2. JSX方式
    在这里插入图片描述

1.2.4.虚拟DOM与真实DOM

在这里插入图片描述

在这里插入图片描述

  1. 虚拟DOM本质是object类型的对象(一般对象)
  2. 虚拟DOM比较“轻”,真实DOM比较“重”,因为虚拟DOM是React内部在用,无需真实DOM上那么多的属性。
  3. 虚拟DOM最终会被React转化为真实DOM,呈现在页面上。
// js创建虚拟节点
React.createElement(标签名,标签属性,标签体内容)

1.3.React JSX

在这里插入图片描述
全称: JavaScript XML
react定义的一种类似于XML的JS扩展语法: JS + XML
本质是React.createElement(component, props, …children)方法的语法糖

1.3.1.作用:用来简化创建虚拟DOM
  • 写法: var ele = <h1>Hello JSX!</h1>
  • 注意1:它不是字符串, 也不是HTML/XML标签
  • 注意2:它最终产生的就是一个JS对象
1.3.2.基本语法规则
  1. 定义虚拟DOM时,不要写引号。
    在这里插入图片描述

  2. 标签中混入Js表达式时要用{}。
    在这里插入图片描述

  3. 样式的类名指定不要用class,要用className。
    在这里插入图片描述

  4. 内联样式,要用style={{key:value}}的形式去写
    在这里插入图片描述

  5. 只有一个根标签
    在这里插入图片描述

  6. 标签必须闭合
    在这里插入图片描述

  7. 标签首字母
    若小写字母开头,则将改标签转为htm1中同名元素,若htm1中无该标签对应的同名元素,则报错。
    若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。

    在这里插入图片描述

1.3.3.js中的表达式和语句区分

在这里插入图片描述
为什么这段代码会报红呢?
因为在react {}包裹的必须是js表达式才可以,for循环是语句,不是表达式

  • 表达式:一个表达式会产生一个值,左侧用一个变量能接到值就是表达式,可以放在任何一个需要值的地方
    • (1).a
    • (2).a+b
    • (3)demo(1) 如果函数没有返回值会自动返回underfined,所以也是能接到值的
    • (4)arr.map()
    • (5).function test(){}
  • 语句(代码),控制代码走向,没有值
    • (1).if(){}
    • (2).for(){}
    • (3).switch(){case:xxxx}

所以上面的代码改用map方法并返回就没问题了
在这里插入图片描述
注意:data数据是数组的形式react会帮我们遍历,如果是对象则不行,控制台报错
在这里插入图片描述
在这里插入图片描述

1.3.4.babel.js的作用

1)浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
2)只要用了JSX,都要加上type=“text/babel”, 声明需要babel来处理

<body>
    <!--  准备容器  -->
    <div id="test"></div>

    <!--  引入babel,用于将jsx转为js  -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel">  /* 此处一定要写babel */
        // 1.创建虚拟DOM
        const VDOM = <h1>Hello,React</h1>/* 此处一定不要写引号,因为不是字符串 */
        // 2.渲染虚拟DOM到页面
       // ReactDOM.render(VDOM,document.getElementById('test'))
    </script>
</body>
1.3.5.渲染虚拟DOM(元素)

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

<body>
    <!--  准备容器  -->
    <div id="test"></div>

    <!--  引入react核心库  -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--  引入react-dom,用于支持react操作DOM  -->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--  引入babel,用于将jsx转为js  -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel">  /* 此处一定要写babel */
        // 1.创建虚拟DOM
        const VDOM = <h1>Hello,React</h1>/* 此处一定不要写引号,因为不是字符串 */
        // 2.渲染虚拟DOM到页面
        ReactDOM.render(VDOM,document.getElementById('test'))
    </script>
</body>

1.4.模块与组件、模块化与组件化的理解

1.4.1.模块

把庞大的js文件拆分成多份

  1. 理解:向外提供特定功能的js程序, 一般一个js文件就是一个模块
  2. 为什么要拆成模块:随着业务逻辑增加,代码越来越多且复杂。
  3. 作用:复用js, 简化js的编写, 提高js运行效率
1.4.2.组件

页面某个能复用的区域,将其封装成组件,就是该区域的所有资源代码功能全部打包到一个组件里

  1. 理解:用来实现局部功能效果的代码和资源的集合(html/css/js/image等等)
  2. 为什么要用组件: 一个界面的功能更复杂
  3. 作用:复用编码, 简化项目编码, 提高运行效率
1.4.3.模块化

当应用的js都以模块来编写的, 这个应用就是一个模块化的应用

1.4.4.组件化

当应用是以多组件的方式实现, 这个应用就是一个组件化的应用

第2章:React面向编程

2.1基本理解和使用

2.1.1使用React开发工具调试

在谷歌浏览器安装React调试工具

  1. 打开谷歌浏览器进入谷歌商店
    在这里插入图片描述
  2. 搜索 React Developer Tools,添加到Chrome
    在这里插入图片描述
  3. 在扩展程序中查看
    在这里插入图片描述
  4. 将该工具固定在浏览器上方(绿色框的图标表示当前网页是否用React编写的,如果是图标则会变亮)

在这里插入图片描述 图标橙色,没有经过打包,开发者模式
在这里插入图片描述 正常图标,打包并且部署到服务器上线了

在这里插入图片描述
5. 开发者模式使用该工具
F12,点击展开箭头
Compontent:网页由多少个组件组成,每个组件拥有的属性
Profiler:记录网站的性能,渲染时间,组件加载时间
在这里插入图片描述

2.1.2定义组件
  1. 函数式组件
<script type="text/babel">
    // 1.创建函数式组件(组件名首字母要大写)
    function MyCompontent(){
    	console.log(this) //undefined
        return <h2>我是函数式组件</h2>
    }
    // 2.渲染组件到id为test的标签内部
    ReactDOM.render(<MyCompontent/>,document.getElementById('test'))
</script>

在函数组件中如果打印this,改this是undefined,而不是像我们写js函数一样,this指向window,原因是jsx代码需要经过babel翻译,babel翻译会开启严格模式,禁止自定义函数里的this指向window。试一试

执行了ReactDOM.render(<MyCompontent…之后,发生了什么?

  • React解析组件标签,标签为大写,找到对应的MyCompontent组件
  • 发现组件是使用函数定义的,随后调用该函数(我们并没有调用函数,是react帮我们调的),将返回的虚拟DOM转为真实DOM,呈现在页面上
  1. 类式组件
<script type="text/babel">
    // 1.创建类式组件
    class MyComponent extends React.Component{
        //render是放在MyComponent的原型对象上
        render() {
            console.log(this) //谁调用this指向谁,此处指向MyComponent的实例对象,也叫组件实例对象
            return <h2>我是类式组件</h2>
        }
    }
    // 2.渲染组件到指定容器中
   ReactDOM.render(<MyComponent/>,document.getElementById('test'))
</script>

注意:必须要继承React.Component父类,必须要写render方法,而且render要有返回值

执行了ReactDOM.render(<MyCompontent…之后,发生了什么?

  • React解析组件标签,标签为大写,找到对应的MyCompontent组件
  • 发现组件是类定义的,随后React帮我们new出来该类的实例对象,并通过实例对象调用原型对象中的render方法
  • 将render返回的虚拟DOM转为真实DOM,随后呈现在页面上

原型链知识点复习:实例对象中都有_proto_(对象原型)属性,该属性指向prototype(原型对象),原型对象中存有类的共享的属性和方法其中的constructor属性指向该类的构造函数,如果在实例对象中的原型对象中找不到对应的方法,则会继续往上查找,直到找到原型对象是Object的为止,如果Object中也没有找到该方法,则会返回null

  1. 简单组件与复杂组件
    有状态(state)的组件为复杂组件,反之为简单组件

2.2. 组件实例三大核心属性state

state是在组件的实例对象中的
在这里插入图片描述

2.2.1状态的基本使用

创建一个天气类 Weather,该类继承自 React.Component,则该类的实例身上会有 props、refs、state等的属性。

state 作为一个对象在我们的项目中使用,用于存储类组件内部的数据。

在类Weather 的构造器中,使用this.state 可以获取到 state。初始时state 为 null,我们在构造器中将 state 定义为对象类型,并为其指定若干属性。

<script type="text/babel">
    // 1.创建组件
    class Weather extends React.Component{
        // 构造器
        constructor(props) {
            super(props)
            // 借助构造器初始化状态
            this.state = {isHot:true}
        }
        render(){
            // 读取状态
            const {isHost} = this.state
            return <h1 onClick={demo}>今天天气很{ isHost?'炎热':'凉爽' }</h1>
        }
    }
    // 2.渲染组件
    ReactDOM.render(<Weather/>,document.getElementById('test'))

    function demo(){
        console.log('标题被点击了')
    }
</script>

事件绑定: 如果demo函数写了括号,如onClick={demo()},此时demo()是一个表达式,表示调用该函数,函数没有返回值会返回undefined,相当于onClick=undefined,把undefined返回给onClick作为回调,这样的话对应的事件会没有任何效果,所以实际绑定的时候函数不需要写括号

2.2.2类中方法中this指向
  1. 自定义函数this指向
    babel翻译开启了严格模式,禁止自定义函数指向window,所以this指向的是undefined
    在这里插入图片描述
  2. 类中的方法this指向
    解决这个问题需要将自定义函数,改写成类中的方法,将function去掉,代码写到类中,
    在这里插入图片描述
    但是此时控制台还是报同样的错误this还是undefined,原因是changeWeather是作为onclick的回调不是实例对象调用是直接调用的就是window调用,类中的方法默认开启了局部的严格模式,this不允许指向window,所以this是undefined
    解析:通过this将找到weather实例对象原型上的方法,作为onclick的回调,实际上就是吧changeWeather方法作为属性赋值给了onclick,然后直接调用(window调用)的onclick,相当于点击h1标签和直接调用方法而不是通过实例对象调用,类中的方法默认会开启严格模式,不是实例对象调用,this会指向undefined,可以看下面js代码的示例来理解
    在这里插入图片描述
  3. 解决类中this指向undefined问题
    使用bind方法,将this指向更正为实例对象,并赋值到实例对象自身的方法
    在这里插入图片描述
2.2.3更改状态setState
  1. 在构造器中声明setState
    通过原型对象找到React.Component组件上的setState()方法进行更改,React不能直接赋值给state更改
    注意:更新状态的逻辑不是整个对象覆盖,而是同名的替换,没有同名的属性保持不变
 class Weather extends React.Component{
	constructor(props) {
	     super(props)
	     this.state = {isHot:true, wind:'微风'}
	     this.changeWeather = this.changeWeather.bind(this)
	}
	changeWeather(){
		let isHot = this.state.isHot
        // 状态必须通过setState就行修改是一种合并的操作,同名的替换掉,没有同名的则保留,setState是React.Component组件上的方法
        this.setState ({isHot: !isHot})
        // 严重注意:状态不可直接更改,下面这行就是直接更改
        // this.state.isHot = !isHot// 错误写法!!
	}
}
  1. 类中方法执行次数分析
    • 构造器调用次数:1次
      在ReactDOM.render渲染组件时,会帮我们new出Weather组件的示例对象,同时调用构造器,new了几次就调用了几次构造器
    • render调用次数:1+n次,1是初始化次数,n是状态更新次数
      执行过程先调构造器,构造器调完了实例对象才出来,实例对象出来了才能掉render
    • changeWeather调用次数:点击的次数
      调用的是自身的changeWeather 而不是原型上的changeWeather
 class Weather extends React.Component{
	constructor(props) { //调用1次
	     super(props)
	     this.state = {isHot:true, wind:'微风'}
	     this.changeWeather = this.changeWeather.bind(this)
	}
	changeWeather(){ //点击了几次就调用几次
		let isHot = this.state.isHot
        this.setState ({isHot: !isHot})
	}
	render(){ //调用1+n次
            const {isHot,wind} = this.state
            return <h1 onClick={this.changeWeather}>今天天气很{ isHot?'炎热':'凉爽' },{wind}</h1>
        }
}
ReactDOM.render(<Weather/>,document.getElementById('test'))
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值