12.22_React_01

React

是一个构建用户界面的javascript库 是脸书开源前端应用框架 是三大框架之一

作用:主要用于编写html页面构建web应用 只提供了视图的渲染 相当于mvc中的v视图层

m:模型

v:视图

c:控制器

特点

  1. 声明式

    • 我们只描绘ui页面骨架部分的构成 相当于html 怎么实现的由react去决定
    const jsx = <div className="app">
        <h1>hello React! 动态变化数据:{count}</h1>
    </div>
    
  2. *基于组件

    • 核心部分 通过各种细小的组件 来组成一整个页面的内容
  3. 学习一次 多处使用

    • 可用之处很多web应用
    • 可以开发移动端react-native
    • 可以开发VR应用react 360

基本使用步骤

  1. 安装
npm i react react-dom 
// react 包是核心,提供创建元素,组件等功能
// react-dom 包提供DOM相关功能
  1. index.html 引入文件 (那个页面需要引入哪个页面)
<script src="./node_modules/react/umd/react.development.js"></script>
<script src="./node_modules/react-dom/umd/react-dom.development.js"></script>
<!-- 注:有引入顺序的影响 react.development先引入 -->
  1. 创建 React元素
const el = React.createElement('h1/创建的html元素', null ,'元素子节点 可以是文字或者可以再嵌套一个节点React.createElement')
// 1.创建的dom元素html名称 
// 2.元素的属性 {title:'这是标题属性'/h1的标题属性, id:'h1'/这是h1的id属性}
// 3.元素的子节点 可以嵌套react元素节点 
// 创建繁琐 并不经常使用 了解就行 后续有JSX代替他来创建元素
  1. *渲染 ReactDOM.render 刚刚创建的React元素
<!-- 创建id为root的dom节点 -->
<div id="root"></div>
<srcipt>
ReactDOM.render('el/渲染节点名称',document.getElementById('root'))
// 渲染到页面
// 1.要渲染的元素名称 
// 2.通过getElementById选中要挂载的DOM节点
<srcipt>

小结: 在开发不同平台时 所使用的渲染方法不同 但是react是必须要导入的

* 脚手架

作用:快速生成项目结构 提高开发效率

  1. 创建脚手架:
npx create-react-app 项目名称
// 创建成功 happy hacking
// npx命令 可以在没有全局安装脚手架时 使用脚手架中的一些命令
  1. 进入到项目根目录 启动脚手架命令:
 npm start 
 yarn start
 // 两者都可以启动 但是yarn需要安装 所以npm比较多
  1. 在index.js中引入React
import React from 'react'
import ReactDOM from 'react-dom'
  1. 创建元素
React.createElement('h1/创建的节点', {})
// 创建繁琐 并不经常使用 了解 JSX代替他来创建元素
  1. 渲染
// 渲染到页面
ReactDOM.render('节点名称', getElementById('root'))
// 此处的root 在index.html页面脚手架自动创建了

生成的项目结构

在这里插入图片描述

// 脚手架创建成功后显示的目录结构
public/公共资源
	index.html	代表的是首页 必需
	manifest.json	PWA应用的元数据
	// PWA 用来指定一些应用的名称、图标等...

src/项目源码 程序员写代码的地方
	index.js	项目的入口文件 必需
	App.js	项目的根组件
	APP.test.js		APP组件的测试文件
	serviceWorker.js	用来实现PWA  可选
	
// 项目调节目录结构
src/
	assets/		资源(图片、字体图标)
	components/		公共文件
	pages/		页面
	utils/		工具
	App.js/		根组件(配置路由信息)
	index.css/		全局样式
	index.js/		项目入口文件(通过render渲染根组件 导入组件库)

index.html 是首页 所有页面的展示页 页面的内容依据此处来展示 创建完元素最后都会要渲染挂载到首页id名为 root的标签中<div id="root"> </div> 类似于vue中的路由占位符

JSX

JavaScript XML 的简写 表示在JavaScript代码中写HTML格式的代码 用于代替react中的创建元素

优点:声明式语法更加直观 与HTML结构相同 提升开发效率

注意点:

  1. 属性名使用驼峰命名
  2. 特殊的几个属性名不能命令 class→className for→htmlFor for在label登录注册输入框中出现 label是在输入框中自动聚焦功能
  3. 在创建时使用小括号()包裹 防止js中自动插入分号
  4. jsx外必须只有一个根元素进行包裹
// 报错,因为根元素的位置有两个并列的<h1>标签
const lut= <h1>tiantian</h1><h1>520</h1>
  1. 在jsx如果双标签中没内容 可写成单标签

在脚手架中可以使用jsx 是因为底层通过@babel/preset-react重新编译了

babel是脚手架内默认自带了配置 不需要手动进行配置

使用步骤

  • 导入react
import React from 'react'
import ReactDOM from 'react-dom'
  • 创建react元素
// 声明的需要插入的jsx元素
let content = <span>我是jsx元素</span>
// 创建的react的h1元素
let h1 = (<h1>我是通过JSX创建的元素+ {content}</h1>)
  • 渲染
// 渲染到页面
// 1.要渲染的元素名称 
// 2.要挂载的DOM节点
ReactDOM.render('h1/渲染节点名称',document.getElementById('root'))

插入表达式 { 名称 }

  • 只能插入表达式三元表达和简单计算、函数的调用和自身的jsx插入
  • 不能插入对象形式{a: 12} 不能插入语句 if、for语句等
  • jsx也是表达式 所以也能放在{}中 为模块化开发做铺垫

* 条件渲染

根据条件是否渲染 JSX 的代码结构

// if
const isload = true
const loadData = () => {
    if(isload){
        return <div> 条件为true时渲染 </div>
    }
    return <div> 条件为false时渲染 </div>
}

// 三元表达式
const loadData = () => {
    return isload ? (<div> 条件为true时渲染 </div>) : (<div> 条件为false时渲染 </div>)
}

// 逻辑与运算符
const loadData = () => {
    return isload && (<div> 条件为true时渲染 </div>)
}
// 通过逻辑中断来实现是否渲染后续代码 要么展示条件为true时候的代码 要么就不展示

* map 列表渲染

在某个位置要渲染一组数据时 使用数组的map() 方法

注:需要给添加key属性 遍历谁给谁添加key属性 避免使用索引号作为key属性

// 一组数组
const user = [
    {id: 1, name:'xxx01'},
    {id: 2, name:'xxx02'},
    {id: 3, name:'xxx03'}
]
const list = (
	<ui>
        {
            user.map(i => <li key = {i.id}> {i.name} </li>)
        }
    </ui>
)

行内样式

cosnt li = (
    <li style={{'color': 'red',"backgroundColor": 'pink'}}></li>
)
// 外面的花括号是插值表达式 里面的花括号是表示对象形式的数据

注:在react中不能直接在标签src路径中写相对路径 需要先导入图片 在标签中填写导入的名称

* 类名

优点:代码结构较为清晰 与逻辑代码分离 写在单独的文件中

  1. 创建react元素
// css文件的导入
import './css/index.css'

cosnt clasname = (
    <h1 class="container">jsx样式</h1>
)
  1. css 样式文件的设置
.container {
    text-align: center
}

react和vue的区别

react是利用js语言本身的能力来编写代码

vue是使用一些框架提供的指令 例如v-model等来编写代码

* react 组件

是react的一等公民 使用react就是在使用组件

页面中的功能都代表是一个组件

特点:

  • 可重复使用
  • 具有独立性互不影响
  • 可以组合使用:通过组和组件来组合成页面

函数组件

使用js的函数或箭头函数创建的组件是函数组件 称为无状态组件

注意点:

  1. 函数名以大写字母开头
  2. 必须要有返回值 return
// 1.定义
// 1.1标准函数
function Hello() {
    return (
        <div>这是第一个函数组件</div>
    )
}

// 1.2使用箭头函数定义 更为简洁
const Hello = () => (<div>这是第一个函数组件</div>)

// 2.渲染使用
// 通过将定义的函数名称作为标签来使用
ReactDOM.render(<Hello />,document.getElementById('root'))

类组件

是使用es6的class创建的组件 称为有状态组件

注意点:

  1. 类名称以大写字母开头
  2. 必须继承React.Component父类 从而在之后可以使用父类中提供的方法和属性
  3. 必须要有render渲染方法
  4. render() 方法内部必须要有返回值 return
// 定义
class Hello extends React.Component {
    render() {
        return (<div>hello 类组件 </div>)
        //在不想要返回值时 return null
    }
}

// 渲染使用
// 通过将定义的类名称作为标签来使用
ReactDOM.render(<Hello />,document.getElementById('root'))

组件抽离单独JS文件

组件作为一个独立的个体 放到单独的js文件中 结构清晰 也方便使用

// 1.创建holle.js文件
// 2. 每个单独的js文件都要需要使用react 所以每个文件需要导入react
import React form 'react'
// 3.创建组件 函数组件或者类组件
function Holle() {
    return (<div>首次抽离单独组件</div>)
}
// 4.通过es6语法进行暴露导出
export default Hello
// 1.在index.js 中导入holle组件
import Hello from './Hello'
// 2.渲染导入的组件
ReactDOM.render(<hello />, document.getElementById('root'))

事件绑定

React事件绑定语法和DOM事件绑定语法相似

语法:on+事件名称/click = {事件处理程序}

注意点:绑定的事件名称采用驼峰命名法 例:onClick

// 类组件中
// 类需要this来保障是当前的实例对象调用了按钮
class Hello extends React.Component {
    // 事件处理程序
    Hello() {
        console.log('类组件触发了点击事件')
    }
    render() {
        return (
        	<button onClick={this.Hello}>按钮</button>
            // 在类组件中 绑定事件需要this 
        )
    }
}
// 在函数组件中 
// 函数绑定事件不需要this是因为直接调用的是函数名称 
function Hello() {
    // 函数事件处理程序
    function handleClick() {
        console.log('函数组件触发了点击事件')
    }
    return (
       <button οnclick={handleClick}>按钮</button>
    )
}
// 渲染组件
ReactDOM.render(<hello />, document.getElementById('root'))

事件对象

是通过事件处理程序的形参获取到事件对象 存放着一些和事件相关的数据

react中的事件对象叫做:合成事件 对象 并不是原生的事件对象 和原生事件对象不要混用

优点:兼容所有浏览器 不需要担心浏览器兼容问题

// 函数事件处理程序
function handleClick(e){
    // e 就是react的事件对象
    e.preventDefault()
    console.log('react的事件对象',e)
}
// 类组件事件处理对象也是类事件处理程序的形参
<a onClick={handleClick}>事件对象</a>

有无状态state 组件

state状态=数据

无状态组件 函数

使用场景:当页面不会变动 只负责展示让数据展示 一直保持静态的时候 使用无状态函数组件

有状态组件 类

使用场景:当页面需要根据用户的变化产生变动时

比如说当用户触发了界面的某个事件 需要页面上展示的数据随之更新 就需要使用有状态的类组件

state 状态

是组件内部的 私有 数据 只能在组件内部使用 如果需要获取私有数据时可以通过组件的通信来获取

class Hello extends React.Component {
    constructor() {
        // super 是es6中必须要写的
        super()
        // state初始化
        this.state = {
            count: 0
        }
    }
    // 简化写法
    state = {
       count: 0
    }
    render() {
    	return (
            <div>初始化的值:{ this.state.count }</div>
            // 拿数据this.state.属性名 必须这样才能拿到数据
        )
   }
}
// 渲染创建的类组件
ReactDOM.render(<Hello />, document.getElementById('root'))

注: 定义state 没有return返回

constructor在什么使用:其实写不写都默认有都会添加 在需要获取this并更改this指向时 需要写在constructor中

setState({ : })

作用:通过setState修改State中的数值 只能通过他来修改State 更新UI界面

数据驱动视图思想: 数据发生变化后 ui视图根据数据变化再发生变化

// 定义类组件
class Hello extends React.Component {
    state = {
        count: 0
    }
	render() {
        return (
            // 注意必须只有一个根元素
            <div>
            	<h1> State: {this.state.count}</h1>
        		<button onClick={() => {
                    // 因为箭头函数没有自己的this绑定 此处的this指向组件实例
                    this.setState({
    					count: this.state.count + 1
    				})
            	}}>+1</button>
            </div>
        )
    }
}
// setState({修改的state属性名:修改的操作})
// 渲染创建的类组件
ReactDOM.render(<Hello />, document.getElementById('root'))

抽离jsx逻辑代码

作用:让分工更加明确 render中只处理ui界面相关代码 将逻辑代码单独抽离到独立的方法中

// 定义类组件
class Hello extends React.Component {
    state = {
        count: 0
    }
	// 事件处理程序 存放逻辑代码的方法
	addCount(){
        // 此处的this为undefined 
        // 方法中的this是谁调用指向谁
        this.setState({
    		count: this.state.count + 1
    	})
    }
	render() {
        return (
            // 注意必须只有一个根元素
            // <!-- 此处会因为this指向的问题找不到addCount方法 -->
            <div>
            	<h1> State: {this.state.count}</h1>
        		<button onClick={ this.addCount}>+1</button>
            </div>
        )
    }
}
// setState({修改的state属性名:修改的操作})
// 渲染创建的类组件
ReactDOM.render(<Hello />, document.getElementById('root'))
事件绑定的this指向

问题原因:原先事件处理逻辑代码是存放在render方法中 使用的是箭头函数 箭头函数没有自己的this指向 会指向离自己最近方法的实例对象 此时render方法是有当前组件的实例对象的 所以this指向没有问题

抽离出来之后事件处理程序变成了普通函数 普通函数的this是谁调用指向谁 此时的this指向了调用它的点击事件 this找不到组件的实例对象 所以this变成了undefined

以下是三种解决方法 ↓

将调用事件的方法改为箭头函数

点击事件后通过箭头函数调用的事件处理程序 利用箭头函数this指向自己最近方法的实例的特性 指向了render拿到了组件实例对象的this

// 事件处理程序 存放逻辑代码的方法
addCount (){
    // 此处的this为undefined 
    // 方法中的this是谁调用指向谁
    this.setState({
    	count: this.state.count + 1
    })
}

render() {
    return (
        // 注意必须只有一个根元素
        <div>
            <h1> State: {this.state.count}</h1>
            <!-- 此处更改为箭头函数 -->
        	<button onClick={() => this.addCount}>+1</button>
        </div>
    )
}

bind

通过调用bind方法将改变后的this指向再次覆盖原先的undefined的this

// 定义类组件
class Hello extends React.Component {
    constructor() {
        super()
        state = {
        	count: 0
        }
        // 将事件处理程序的this 更改后重新存入
        // 此时需要获取this 所以写在constructor中
        this.addCount = this.addCount.bind(this)
    }
    
}
// 事件处理程序addCount 省略...

render() {
    return (
        // 注意必须只有一个根元素
        <div>
            <h1> State: {this.state.count}</h1>
            <!-- 在constructor中重新存入了this 所以不会出现问题 -->
        	<button onClick={this.addCount}>+1</button>
        </div>
    )
}

*** 将调用的事件改为箭头函数**

将事件处理程序的函数改为箭头函数就能解决

注:是实验性语法 需要有babel的存在才可以直接使用 一般脚手架会默认配置babel 是最为便捷的方法

// react在事件处理函数中的this是未定义
// 在类组件的第一层定义箭头函数名= () => {}
// 事件处理程序 存放逻辑代码的方法
addCount = () => {
    // 此处的this为undefined 
    // 方法中的this是谁调用指向谁
    this.setState({
    	count: this.state.count + 1
    })
}

// render省略...

render() {
    return (
        // 注意必须只有一个根元素
        <div>
            <h1> State: {this.state.count}</h1>
            <!-- 在constructor中重新存入了this 所以不会出现问题 -->
        	<button onClick={this.addCount}>+1</button>
        </div>
    )
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值