react简介
React用于构建用户界面的javascript库, 官方提供核心的一些内容,需要靠周边生态来支撑他的运行。
React-起源于facebook内部项目。
React一般被用来作为MVC中的V层,它不依赖其他任何的库
React的思想非常独特,性能出众
React的语法是jsx,通过使用这种语法,可以在react代码中直接混合使用js和html来编写代码
react思想:
- 解决UI层面的设计。
- React有两个分支,一个分支WEB端(React-DOM)、一个分支移动端(React-Native)。
官方:
中文网:
react特点
- 组件化开发思想:SPA,组件需求,JSX
- 社区完善,适合于大型的web应用开发
- facebook团队维护,版本稳定,持续更新
- 开发适用于多个场景
- 虚拟DOM
- DOM diff算法
react高效的原因就是虚拟dom和dom diff算法
Vue 和 React 的区别是什么?
-
Vue 是基于 MVVM 架构的前端框架,React 是基于 MVC 架构的前端库;
-
Vue 支持双向数据绑定,React 不支持双向数据绑定;
-
Vue 是通过响应式的方式来侦听数据变化并更新组件,React 中是通过调用 setState 方法来修改数据更新组件;
-
Vue 官方有配套的状态机和路由,React 官方没有,需要使用第三方的路由和状态机插件;
-
Vue 主要采用的是模版语法来编写组件,而 React 主要采用的是 JSX 的语法来编写组件;
-
Vue 封装得更深,上手入门更容易,React 封装得较少,上手入门较难,但使用更灵活;
核心模板的组成
React当成库来使用,你们只需要在html项目中引入react.js可以开始开发。
1、首先我们去React官网reactjs.org/下载开发所需要的文件。…
2、初学React的小伙伴们,咱们需要下载两个JS文件。
分别是react.development.js与react-dom.development.js。
-
react.development.js:React的核心库,用于创建UI
-
react-dom.development.js:提供与DOM相关的功能。用于将创建的UI渲染到浏览器中。
注: 为什么要把 React 和 ReactDOM 分开呢?
React 在v0.14以前是沒有 ReactDOM 的,全部功能都包含在 React 里, 因为有了 ReactNative,才分开。React 只包含了 Web 和 Mobile 通用的核心部分,负责 Dom 操作的分到 ReactDOM 中,负责 Mobile 的包含在 ReactNative 中。
ReactDom是React的一部分。ReactDOM是React和DOM之间的粘合剂。
创建虚拟dom
需求: 利用虚拟dom渲染的方式新建dom节点,并显示'hello react'
通过React.createElement的方式
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
</head>
<body>
<div id="app"></div>
<script>
const str = '你好,世界';
// 通过React.createElement 创建虚拟dom
// React.createElement(type, props, children)
const vDom = React.createElement('div',{
className:'test',
style:{color:'red'}
},
str);
//浏览器解析出来: <div className="test">hello react</div>
// 把虚拟dom转化成真实的dom,
// ReactDOM.render 是 React18版本之前 的最基本方法,用于将虚拟dom转为 HTML 语言,
// 并插入指定的 DOM 节点。
// ReactDOM.render(vDom,document.getElementById("app"))
const root = ReactDOM.createRoot(document.getElementById("app"))
// root.render 将虚拟dom转化为真实dom
root.render(vDom)
</script>
</body>
</html>
const root = ReactDOM.createRoot 创建根节点;
root.render 方法 把虚拟dom转换为真实dom 并渲染在模板中
在 React 中,"root" 是一个指向顶层数据结构的指针,React 用它来跟踪要渲染的树。
涉及知识点:
为啥要引入react和reactDom 2个包?
如何通过react创建 虚拟dom?
如何使用ReactDOM将模板转化为html语言?
通过jsx语法的方式
Babel:可以将ES6代码转为 ES5 代码,这样我们就能在目前不支持 ES6 浏览器上执行 React 代码。
Babel 内嵌了对 JSX 的支持
JSX=JavaScript and XML(HTML)
jsx的特点:
- 开发代码更简洁
- 性能更好,
- 执行更快,编译代码的时候就会进行代码优化
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
已经要记得在script里加上type="text/babel" 来对jsx语法的支持
<script type="text/babel">
// 通过jsx创建虚拟dom
const str = 'hello react'
var domStr = <div className="test" style={{color:'red'}}>{str}</div>;
// const vDom = <h1 id="myId">hello react</h1>
// 把虚拟dom转化成真实的dom
ReactDOM.render(domStr,document.getElementById("app"))
</script>
- 你需要引入一个babel包, 内置了jsx的语法支持, 可以让你在模板中写html和js
- 在script标签要引入
type="text/babel" - jsx中模板渲染通过{}
- 样式:可以使用内部style定义样式 , 也可以使用外部样式 , 然后通过className来使用
注意:style中你看到2个{{}}, 外面一层代表 模板渲染的语法, 里面一层代表style是一个对象的形式,而且属性都是以驼峰式命名的, 比如background-color - > backgroundColor
创建虚拟dom的两种方式
-
React.createElement
-
jsx
react中样式处理
在JSX中使用css样式,有两种方案
-
行内样式(内联样式)
直接在标签上面添加css样式
var domStr = <div className="test" style={{color:'red'}}>{str}</div>;如果你要标签上面直接写style,必须动态绑定样式.css样式有多个,里面值也是一个对象, 所以你看起来是双括号{{}}
JSX已经将CSS代码重新封装了一次.样式名需要是驼峰式
backgroundColor->>background-color
只要css代码原来有连字符,都是驼峰命名
-
外部样式
将样式代码写到外部去,引入进来使用
class---JSX要求你必须className
jsx语法逻辑处理
练习:jsx逻辑处理及运算
var a1 = true;
var price = 1000;
var divD = <div className="a">{a1?'北京':'上海'} {price * 10}</div>
ReactDOM.render(
divD,
document.getElementById("app")
);
总结:
-
三目运算符来进行逻辑处理
<div>{state?"开启":"关闭"}</div> -
运算符处理,支持加减乘除运算符
<div>{price * 10}</div> <div>{price / 10}</div> <div>{price > 10}</div> <div>{user && user.name}</div> <div>{show || show1}</div>
jsx数据动态渲染
实践需求:
var names = ['苹果','香蕉','桃子'];
利用jsx的语法把数组names 解析成列表进行渲染
列表结构
<ul><li>香蕉</li></ul>
<div id="app"></div>
<script type="text/babel">
const arr = [{
title:'苹果',
price:10
},{
title:'西瓜',
price:20
}]
var arrList = arr.map((item,index)=>{
return <li key={index}>{item.title} -- {item.price}</li>
})
console.log(arrList);
const vDom = <ul>
{arrList}
</ul>
const root = ReactDOM.createRoot(document.getElementById('app'))
// 把虚拟dom转换为真实dom 并渲染在模板中
root.render(vDom)
</script>
总结:
-
React提供JSX进行动态遍历的时候,实际上就是通过map拼接成我们想要的数组形式
{list.map(item => {})}---->[<li></li>,<li></li>]JSX模板是可以渲染数组,但是里面内容不能是对象
-
遍历过程中也需要加上key,必须唯一
-
数据渲染以后都是页面中进行遍历,这样数据一旦发生变化,页面自动更新
类的定义和继承回顾
// 类的名字第一个字母大写
class People {
static category = '人类' // 相当于是一个全局变量, 访问是 People.category
// 构造函数, 构造器
constructor(name,age){
this.username = name;
this.age = age
}
say(){
console.log(this.username);
}
run(){
this.say()
}
}
// 访问静态属性
// console.log(People.category);
// var p1 = new People('xiaohua',20);
// console.log(p1);
// p1.say()
// 定义子类
class Teacher extends People {
constructor(username,age,school){
super(username,age); // 必须有super关键字
this.school = school; // 定义自己的属性
}
walk(){
console.log(this.school);
console.log(this.username+'走路');
}
}
var t1 = new Teacher('xiaobai',30,'武汉')
t1.walk();
组件的概念
使用组件的方式进行编程,可以提高开发效率,提高组件的复用性、提高代码的可维护性和可扩展性
React定义组件的方式有两种
类组件:React16.8版本之前几乎React使用的都是类组件
函数组件:React16.8之后,函数式组件使用的越来越多
组件的定义的两种方式
定义类组件
类组件:是指通过ES6类来定义的组件称为类组件,React中定义类组件有如下约定
-
类组件首字母大写
-
类组件必须要继承React.Component父类,这个父类中的相关方法和属性都能被继承
-
类组件中必须要有一个render方法
-
这个render必须要有返回值,返回值的内容就是这个类组件的结构(jsx)
class Hello extends React.Component {
// constructor(){
// 组件内部数据可以定义在构造器里面
// super();
// this.state = {
// name:'alice'
// }
// }
// 简写
state = {
name:'alice'
}
render() {
// console.log(this);
return <div>{this.state.name}</div>
}
}
类组件和函数式组件
- 注意
- 组件名字一定要大写
- 虚拟dom只能有一个根标签, 必须有结束标签
- 必须有一个render方法, render方法里必须有一个return返回值
- 定义组件内部数据 必须要使用state
- 在模板中访问组件内部数据的时候, 要使用this (组件的实例化对象) this.state.属性名
- render渲染组件的基本流程
-
react内部会创建组件的实例对象
-
得到包含虚拟dom并且解析为真实的dom
-
插入指定的页面元素里面
-
react 16.8版本之前 类组件是比较流行的, 因为类组件是有状态的, 你可以访问this,函数组件没有this, 所以用的很少。 但是随着发展, 目前已经到了版本18了, react官方推出了hooks,让函数组件功能变得强大起来, 目前也开始流行了
类组件的事件处理
vue中通过什么绑定事件处理函数?v-on指令来实现绑定,可以通过他的简写@事件类型方式来绑定事件的
在React中通过onClick属性来实现单击事件的绑定的,常见的写法
1.直接在标签中通过onClick={()=>{}}来实现事件的绑定
2.在标签中通过onClick={this.类中的普通成员方法}来进行绑定
3.在标签中通过onClick={this.类中的箭头函数}来进行绑定
4.在标签中通过onClick={()=>{this.函数名称()}}
建议使用箭头函数写法代替普通方法
<div id="app"></div>
<script type="text/babel">
// 给予react基类组件定义一个react类组件
class Hello extends React.Component {
// 构造器
constructor(props){
super(props);
this.state = {name:'hong'}
}
sayHello(lang){
console.log('说话- hello');
this.setState({
name:lang
})
}
// 推荐
runFun=(ev)=>{
console.log('跑步');
}
// render函数返回组件的页面结构
render(){
console.log('我渲染了');
return <div>
<p>你好啊</p>
<p>我的名字:{this.state.name}</p>
{ /* 1. 箭头函数传参 */ }
<button onClick= {()=>this.sayHello('中文')}>点击我</button>
{ /* 2. bind函数传参 , 改变作用于 */ }
<button onClick= {this.sayHello.bind(this,'中文')}>点击我</button>
{ /* 3. 箭头函数定义 不传参, 通过data-方式传参, 跟微信小程序传参一样 */ }
<button tag="1" data-kind='2' onClick={this.runFun}>跑步传参</button>
{
/* 对比推荐:
在定义函数的时候使用箭头函数定义, 采用data-的方式传参,调用的时候采用
箭头函数定义 不传参 使用 */
}
</div>
}
}
ReactDOM.render(<Hello/>, document.getElementById('app'))
</script>
总结:
react组件的render函数何时调用
1.第一次初始化的时候
2.页面数据更新的时候
3.强制更新forceUpdate的时候
render渲染组件的基本流程
- react内部会创建组件的实例对象
- 得到包含虚拟dom并且解析为真实的dom
- 插入指定的页面元素里面
类组件的state
vue框架和React框架最大的一个好处就是不需要开发人员去操作DOM,只要大家操作了数据,自动DOM元素会发生改变,这种操作称为响应式
在vue中响应式数据主要来自两个部分
组件内部响应式数据是定义在data选项
来自子组件外部通过props来定义的
在React中也是一样,如果要定义响应式数据,组件内部的数据是定义在组件的state中,组件外部的数据是定义在props中
1、有状态组件和无状态组件
类组件是有状态组件:因为一个组件的状态是存放在类的实例上,state,props都是存在this上,所以类组件被称为有状态组件
函数组件是无状态组件:函数组件都没有this,函数不能存放状态
类组件比较强大,函数组件比较单一,类组件可以完成复杂的功能,但是函数组件是简单的组件
在React16.8版本之后引入hooks可以让函数组件也能操作状态
总结:React16.8之前函数组件是无状态组件,几乎很少使用
2、state的基本使用
第一步:定义数据,可以在构造函数内部,也可以在构造函数外部
第二步:获取数据,在使用数据的时候为了提高读取性能,最好使用解构赋值方式
第三部:修改数据的时候一定要使用setState({})来修改数据,这个方法是一个异步方法
第一步:定义数据
class Counter extends React.Component{
//简化语法
state={
count:0
}
render(){
return (
<div>
<h2>计数器</h2>
</div>
)
}
}
export default Counter;
第2步、获取数据
通过this.state获取数据
class Counter extends React.Component{
constructor(){
super();
this.state={
count:0
}
}
render(){
return (
<div>
<h2>计数器</h2>
<span>{this.state.count}</span>
</div>
)
}
}
export default Counter;
在使用数据的时候,最好使用解构赋值的方式,这样能够提高性能
import React, { Component } from 'react'
export default class Counter extends Component {
state = {
num: 0
}
constructor() {
super()
}
render() {
const { num } = this.state;
return (
<div>
<h1>计数器</h1>
<span>{num}</span>
</div>
)
}
}
第3步、修改数据
状态是可以改变的
语法:this.setState({要修改的数据})
注意:不要直接修改state中的数据,这样是错误的
setState()作用:1.修改state 2.更新UI
import React, { Component } from 'react'
export default class Counter extends Component {
state = {
num: 0
}
constructor() {
super()
}
render() {
const { num } = this.state;
return (
<div>
<h1>计数器</h1>
<span>{num}</span>
<button onClick={() => {
this.setState({
num: this.state.num + 1
})
}}>+1</button>
</div>
)
}
}
3、类组件的props属性
props的默认值
React的props的默认值设置有两种方法
-
类名.defaultProps={key:value}export default class UserInfo extends React.Component{} UserInfo.defaultProps={ title:'暂无标题', name:'暂无名称' }
-
static defaultProps={key:value}(推荐)export default class UserInfo extends React.Component{ static defaultProps={ title:'暂无标题', name:'暂无名称' } }props的只读性
通过props传递进来的基本类型,组件内部不能直接更改
实践作业-简单切换
需求:
- 利用类组件实现一个简单tab切换, 内容相应改变
- 新闻按钮激活时, 内容显示新闻内容,关于我们按钮激活时 内容显示关于我们的内容
- 用一个组件实现即可,新闻内容和 关于我们无需另外写组件
涉及知识点巩固:
- 类组件的使用
- 动态渲染变量{}的使用
- jsx语法的使用
- onClick事件绑定以及this作用域的使用
- 组件命名首字母大写
代码演示:
<script src="lib/react.development.js"></script>
<script src="lib/react-dom.development.js"></script>
<script type="text/javascript" src="lib/babel.min.js"></script>
<style>
ul, li { list-style: none;}
.menu-list { display: flex;}
.menu-list li{ margin-right: 20px; cursor: pointer; }
.active {
color: #f60;
}
</style>
<body>
<div id="my"></div>
<script type="text/babel">
/*组件*/
/*定义标题*/
class TabList extends React.Component{
constructor() {
//关键字 ,父类/子类继承的一种方式
super();
this.state = {
flag:1
}
};
btnSwitchChange(type){
this.setState({
flag:type
})
};
render(){
var flag = this.state.flag;
return (
<div>
<ul className="menu-list">
<li className={flag==1 ? 'active':''} onClick={()=>this.btnSwitchChange(1)}>新闻</li>
<li className={flag==2 ? 'active':''} onClick={()=>this.btnSwitchChange(2)}>关于我们</li>
</ul>
<div>
{flag==1 ? <p>新闻内容</p> : <p>关于我们内容</p>}
</div>
</div>
)
}
};
ReactDOM.render(
<TabList />,
document.getElementById("my")
);
</script>
</body>
实践作业tab切换
进阶需求:
- 新增新闻组件 和关于我们组件
- 点击新闻按钮, 显示新闻组件里的内容
- 点击关于我们按钮, 显示关于我们组件里的内容
知识点:
巩固类组件的使用规范
实践作业-todo列表
作业:
利用类组件完成一个todolist
- 可以添加一条任务,添加完毕清空输入框
- 可以删除数据
代码演示:
<div id="app"></div>
<script type="text/babel">
class TodoList extends React.Component {
state = {
currentVal:'',
todoList:[{
name:'画画',
isFinshed:false
}]
}
updateValue=(ev)=>{
const value = ev.target.value;
this.setState({
currentVal:value
})
}
addTask=()=>{
let todos = this.state.todoList;
if(!this.state.currentVal) return;
todos.push({
name:this.state.currentVal,
isFinshed:false
})
this.setState({
todoList:todos
})
//直接操作dom
var inputDom = this.refs.input;
inputDom.value =''
}
deleteTodo=(index)=>{
console.log(this);
this.state.todoList.splice(index,1);
this.setState({
todoList:this.state.todoList
})
}
render(){
const {currentVal,todoList} = this.state;
return (
<div>
<input type="text" onChange={this.updateValue} ref="input" />
<button onClick={this.addTask}>添加</button> <br />
<ul>
{todoList.map((item,index)=>{
return <li key={index}>{item.name} --- {item.isFinshed ? '完成' :'未完成'}
<button onClick={()=>this.deleteTodo(index)}>删除</button> </li>
})}
</ul>
</div>
)
}
}
const root = ReactDOM.createRoot(app)
root.render(<TodoList /> )
</script>
然后在项目中把封装这个todolist
第一步: 以一个组件为整体封装成TodoList.jsx
第二步:拆分成TodoHeader.jsx 和 TodoItem.jsx列表 , TodoListLink.jsx作为主要容器
准备工作
-
必须安装nodejs 注意:安装nodejs稳定版本
-
用yarn替代npm
yarn 包管理器
Yarn是facebook发布的一款取代npm的包管理工具, 类似npm的包管理工具, 参考官方文档yarn.bootcss.com/
但是比npm更快速,可以离线缓存,在下一次安装这个包时,甚至不需要有互联网连接,因为包是从磁盘离线安装的
特点:
-
速度超快。 Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。
-
超级安全。 在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。
-
超级可靠。 使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。
全局安装:
使用 npm 全局安装 yarn:
npm install yarn -g
查看版本
要检查电脑中是否有安装 yarn,可以通过以下命令来查看 yarn 的版本
yarn --version
设置镜像
yarn config set registry http://registry.npm.taobao.org/
yarn config set sass_binary_site http://cdn.npm.taobao.org/dist/node-sass
查看配置: yarn config list // 显示所有配置项
常用命令
项目初始化, 用于在项目中生成package.json文件
yarn init -y
下载依赖包
yarn add 包名称
yarn add 包名称@版本号
# 局部安装开发环境的依赖包(上线后不需要)
yarn add 包名称 --dev
删除依赖包
yarn remove 包名称
根据pageage.json下载项目所需依赖包
yarn 或者 yarn install
全局操作
# 全局下载依赖包
yarn global add 包名称
# 删除全局的指定依赖包
yarn global remove 包名称