react 有手机 app 扩展库 --ReactNative 使用原生 JS 开发手机 app
React 开发分两种方式 1.脚本方式 2.脚手架方式
脚本方式
- 引入 react.js脚本
- React提供两个类
React:负责创建元素
ReactDOM:负责渲染元素,其他的元素中 - 利用 React 创建元素
例:let h3 = React.createElement( "h3" ,{ id:"time", className:"time"}, "当前时间:10:12" )
- 利用 ReactDOM 渲染到"id=root"标签中
React.render(h3,"root")
学习JSX
- JSX:在 js 中书写 xml格式的DOM 操作代码; html 是 xml 中的一种,即标签语言
- JSX属于特殊语法,浏览器不认识,浏览器无法识别,因此需要 引入babel 工具进行翻译,并且在 script 标签上加 type="text/babel",代表此脚本必须 使用babel 编译
- 例:
// 把当前时间展示到 id="root" 的标签中
let tiem = "10:56"
let h3 = <h3 className="danger" id="time">当前时间:{ time }<h3>
ReactDOM.render(h3,root);
注意:vue,angular,小程序中差值表达式为 {{ js 代码 }},而 JSX 中为 { js 代码 }
学习组件
- 组件:组成页面的零件
- 组件的特征:复用性
- React 采用 函数 和 类 制作组件
1)函数:适合简单组件制作
2) 类:适合复杂组件制作 - 组件函数名要求大坨峰写法:更容易区分组件和普通函数
- 例:
函数方式
function HelloWord () {
return <h1>hello word!</h1>;
};
ReactDOM.render(HelloWord (),root);
// 语法糖写法,babel自动编译成 HelloWord()
ReactDOM.render(<HelloWord/>,root);
// render() :非新增操作而是会覆盖
// 复用性:
let more = (<div>
<HelloWord/>
<HelloWord/>
<HelloWord/>
</div>)
ReactDOM.render(more,root);
类方式
1)类方式制作组件:创建具有强大能力的组件要求必须继承父类
class HelloWord extends React.component {
render(){
return <h1>Hello Word!</h1>
}
}
// 使用
React.render(new HelloWord().render(),root);
// 语法糖写法
React.render(<HelloWord/>,root);
// 复用行
let more = (<div>
<HelloWord/>
<HelloWord/>
<HelloWord/>
</div>)
React.render(more,root);
父子传参
1)函数组件传参
function HelloWord (props) {
return <h1>hello,{props.name}</h1>
};
React.render(HelloWord( {name:"中国"} ),root);
// 语法糖
React.render(<HelloWord name="中国"/>,root);
2)类组件传参
this.props 来自于父类的constructor 方法,该方法 new 时自动触发
class HelloStar extends React.component {
// 带有 this 前缀说明props 是成员属性,成员属性可以跨方法使用
// constructor(props) {
// this.props = props;
// }
render() {
return <h1>hello,{this.props.star}</h1>
}
}
ReactDOM.render(new HelloStar({name:"林俊杰"}),render(),root);
// 语法糖
ReactDOM.render(<HelloStar name="林俊杰"/>,root);
事件
- 用户可以通过操作 UI触发各种事件,如点击事件、失焦事件等
- 函数书写建议使用箭头函数不会出现 this 指向问题
class Demo extends React.component {
name = "俊杰"
show = () =>{
console.log(this.name)
}
render() {
// 事件的绑定
// vue 中 v-on:click="方法名",简写@click="方法名"
// React 中 onClick="方法名"
// React 中 {}中的方法会直接执行 ,所以方法是否加()是有区别的,加会直接执行,不加事件触发执行
return (
<div>
<button onClick={this.show}>点击触发~</button>
<button onClick={this.show()}>点击触发~</button>
</div>
)
}
}
状态值
- React中,使用state存储数据,通过{ }显示在页面上,利用 setState( )更新数据,可以让 UI 同步刷新
- state状态值只有使用类组件才能使用
- vue 中只要修改数据页面就会更新,React 中必须使用 state 和 setState 配合
- state 中的数据必须使用 setState 页面才会刷新页面,setState 会做两件事 修改数据+修改 UI
class Demo extends React.component {
state = {
count:1
}
_addCount = ()=>{
// setState是异步操作,方法第二个参数是回调函数,在数据渲染成功时触发
this.setState({count:this.state.count + 1},()=>{
console.log("回调函数",this.state.count);
})
}
// 类中的方法有很多,通常分为两种
// 1)事件绑定 2)普通方法
// 约定与事件绑定的方法带前缀 _
render(){
return (
<div>
<h3>{this.state.count}</h3>
<butten onClick={this._addCount}>点击+1</butten>
</div>
)
}
}
ReactDOM.render(<Demo/>,root);
安装脚手架
- 脚手架是一个工具,可以快速搭建项目的基本架构完成所需资源的下载和配置
- 脚手架安装要求 node >=8.10 &&npm >= 5.6 查看当前版本 node -v && npm -v
- React 脚手架安装命令: npm i -g create-react-app,创建项目命令: create-react-app 项目名
- 创建的项目名不允许有大写字母
-
安装官方插件,rcc 生成项目基本结构,vscode 不识别 JSX 语言,切换语言为JavaScript React才会有代码提示
- 项目的启动流程
1)项目下执行 npm start 命令会开启一个服务器,服务器程序唯一标识 端口号:3000
2)浏览器上访问localhost:3000
3)webpack工具:脚手架自动配置了此工具,项目运行时会自动打包index.js引入到 index.html 中
4)index.js 引入了 App.js并且渲染到 id="root" 的标签上
5)App.js 项目的根组件 - React项目是 SPA 项目:Single web Page Application,即单网页应用,只有一个页面,通过路由切换局部内容,实现页面变更
条件渲染
- React 的条件渲染不同于 Vue ,需要单独写一个函数并在渲染出调用
- 为什么调用时 没有 this 指向问题?此方法不是事件触发而是刷新时触发,this 指向不是 window
- 判断条件一定是 state相关的值,setState 更新时就会自动刷新更新 UI
show() {
if(this.state.num == 0) return <h1>000</h1>
if(this.state.num == 1) return <h1>111</h1>
}
render() {
return (
<div>当前号码</div>
{this.show()}
)
}
列表渲染
- React 中的列表渲染需要单独写一个方法去改造数组,实现数组里放 JSX 语法渲染
- 循环数组的每项都需要带一个唯一标识 key
- 使用数组的 map 方法会更简单的实现列表渲染
arr = [11,22,33,44]
arrFn () {
let arr2 = [];
this.arr.forEach((item,index) =>{
arr2.push(<div key={index}>{item}</div>)
});
return arr2;
}
// 使用数组的 map 方法
arrMapFn () {
return this.arr.map((item,index)=>{
return <div key={index}>{item}</div>
}
)
}
render () {
return (
<div>{this.arrFn()}</div>
)
}
动态风格样式
- 即在页面展示时 样式能动态的发生变化
- JSX语法中样式需要写成对象类型
- 样式分为两种写法___ 1)内联式 style ___2)外部样式 css文件+class
1)内联式
//点击按钮使文字变大
state={
size:18
}
render() {
return (
<div style={{fontSize: this.state.size + "px"}}>Hello</div>
<button onClick={() => this.setState({size : this.state.size + 2})}>点击变大</button>
)
}
2)外部样式
// App.css
.style1 {
background-color: #fff;
}
.style2 {
background-color: #000;
}
.style3 {
background-color: #999;
}
// App.js
import "./App.css";
state={ size:18 }
styleFn() {
let num = this.state.size;
if(num == 20) return "style1"
if(num == 22) return "style2"
if(num == 24) return "style3"
}
render () {
return (
<div className={this.styleFn()}>hello</div>
<button onClick={() => this.setState({size : this.state.size + 2})}>点击变大</button>
)
}
双向数据绑定
- from表单中的元素,通常能够与用户交互,此时会出现数据绑定到 UI 元素,UI 元素因为用户操作发生变化,同步更新到数据的情况,即为双向数据绑定
- 用户更改 UI 会触发 onChange方法,使用 onChange方法实现UI 变化时数据同步
- 事件触发的方法,会带 event 事件对象参数
- 事件默认是 Dom 事件,但在 React 中对 Dom 事件进行了处理,处理之后的事件叫做 同步事件
- 同步事件:把值传入后会自动销毁自身,要想打印事件中的值必须调用event.persist(),对读值没有影响,且不是实时的值
state={
uname: "",
upwd: ""
}
_changeN=(event)=>{
// event.persist()
// console.log(event)
this.setState({uname:event.target.value})
}
_changeP=(event)=>{
// event.persist()
// console.log(event)
this.setState({upwd:event.target.value})
}
render(){
return (
<input/ type="text" placeholder="用户名" value={this.state.uname} onChange={this._changeN}>
<input/ type="password" placeholder="密码" onChange={this._changeP}>
<button>登录</button>
)
}
生命周期
- 组件生成、更新、销毁的过程
- 组件的每个关键过程都会有钩子函数被触发
- componentDidMount钩子函数会在被挂载时触发,通常在这个钩子函数中发送请求,获取数据
- componentWillUnmount钩子函数会在组件被销毁时触发,通常在这个钩子函数中销毁一些资源防止内存泄漏,例如定时器
- componentDidUpdate钩子函数会在组件更新时触发,有两个参数props,state
1)props:属性,接收外来传参,props是旧值,新值是 this.props
2)state:状态值,组件本身的变化,state 是旧值,新值是 this.state - shouldComponentUpdate钩子函数的两个参数会返回即将变化的值,以此来判断是否更新组件,提高 React 的渲染效率,面试会经常问
import React, { Component } from 'react'
export default class App extends Component {
state = {
show: false
}
isShow() {
if(this.state.show) return <Son/>
}
render() {
return (
<div>
{this.isShow()}
<button onClick={()=>this.setState({show:!this.state.show})}>点击</button>
</div>
)
}
}
class Son extends Component {
componentDidMount() {
console.log('componentDidMount钩子函数触发,组件挂载');
};
componentWillUnmount() {
console.log('componentWillUnmount钩子函数触发,组件销毁');
};
componentDidUpdate(props,state) {
console.log('旧值', props, '新值', this.props)
console.log('旧值',state,'新值',this.state)
};
shouldComponentUpdate(props, state) {
// props,state 代表即将变化的值,即即将展示的值
if (state.count % 2) {
// false 代表组件不会刷新到页面上,则 didupdate 函数也不会触发
return false
} else {
return true
};
};
render() {
return (
<div>我是子组件</div>
)
}
}