介绍
- 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混写
- 遇到 <>,JSX 就解析成 HTML;遇到 {}按 JavaScript 解析。
- 虚拟 DOM 只允许有一个根节点
- JSX 标签可以相互嵌套注意换行和缩进,增强代码的可读性
- 建议使用小括号括将 JSX 代码括起来 ,防止分号自动插入的 bug
- 通过 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
- 初始化
this.state = {
age: 18,
money: 1000,
msg: ''
}
- 获取状态:this.state.xxx
- 修改状态,这是一个异步的方式,想要获取最新的值,可以在回调函数中获取
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实现组件传值:
- 父传子:通过组件的属性传递
// 在父组件中
<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的区别:
- state: 是组件内部的状态数据,state的数据不能直接修改,如果需要修改需要通过特殊方法setState()进行修改.
- props:一般用于组件之间通信,并且通常是父组件向子组件传递数据,通过this.props来接收.this.props的数据不能直接修改,如果需要修改,则需要通过父组件中的setState来进行修改.