官网文档 - https://react.docschina.org/docs/getting-started.html
本篇文章会介绍react项目利用脚手架如何搭建,以及它的基础语法和属性
1.react项目搭建
脚手架搭建
全局安装脚手架 yarn global add create-react-app
创建项目 create-react-app 项目名
进入并启动 cd 项目名 =》 yarn start
注意:
(1) 有可能会全局安装有问题,则不进行全局安装
局部安装脚手架 yarn add create-react-app
创建项目 npx creat-react-app 项目名
进入并启动项目 cd 项目名 =》 yarn start
(2)有可能会出现全局安装了webpack 和现在安装的版本不一致,卸掉掉安全局的webpack
npm uninstall webpack -g
yarn remove webpack
2.文件解析
-src
-index.js 入口文件
//引入插件
import React from 'react';
import ReactDOM from 'react-dom';
//参数一:组件或者元素
//参数二:目标容器 - 根节点
ReactDOM.render(<p>测试</P>,document.getElementById('root'))
//底层原理: ReactDOM.render(React.creatElement('p',null,'测试'),document.getElementById('root'))
3.jsx
(1)什么是jsx?
jsx既不是字符串也不是 HTML,是一个 JavaScript 的语法扩展(虚拟DOM),在 JSX 语法中,你可以在大括号内放置任何有效的JavaScript 表达式,Babel 会把 JSX 转译成一个名为 React.createElement()
函数调用
(2) jsx和HTML的区别是什么?
下面两个例子是完全等效的
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
4.定义组件
(1)什么是组件? - 组件就是具有独立功能的一个部分
(2)如何定义一个reacrt的组件(js文件)
1.工厂函数进行定义
function MyComponent(){
return <h2>工厂函数组件</h2>
}
2.re6类组件进行定义
//引入核心依赖 react-dom只需要入口文件引入
import React from 'react'
//引入css文件可直接使用 - webpack的原因,可以进行解析
import './test.css'
//创建组件 - 类名 == 创建的文件名
class Hello extends React.Component {
//在prototype中
//组件内的方法推荐用箭头函数
show()=()=>{
//this为Hello的实例
console.log(this)
}
//必须含有render
//render函数就是返回一个jsx对象,当前组件的结构
//返回的 == vue的 template 虚拟DOM节点
render(){
return (
//this 是Hello的实例
<div onClick = { this.show } className="test" style ={{color:"red"}}>hello word</div>
)
}
}
注意:区别 - 类组件内可以有state属性
vs插件 - ES7 React/Redux/GraphQL/React-Native snippets
rcc 快速进行创建js文件内容
(3)列表渲染
jsx可以自动渲染jsx数组( 数组里面的每一个元素都是JSX都是jsx对象)
import React, { Component } from 'react'
const list = [
{id:0,name:'张三',age:18},
{id:1,name:'李四',age:12},
{id:2,name:'王',age:20},
{id:3,name:'张二三',age:32},
]
export default class Listcomp extends Component {
render() {
// map将返回的数据会自动装入数组中
return (
<div>
<ul>
{
list.map((item,key)=>{
return <li key={item.id}>我是{item.name},年纪:{item.age}</li>
})
}
</ul>
</div>
)
}
}
(4)插槽 - 渲染标签之间的内容 - 使用 this.props.children
a.js
import Main from '路径',
<main>我是插槽之间内容</main>
b.js
render(){
return (
<div>this.props.children</div>
)
}
4.react中的属性
(1)外部数据 - 属性 - props - 外部传值
//组件传值 - 与vue父传子的传值方式相同 属性名='传递的属性值'
import Hello from '路径'
<Hello name='aa'/>
//接收值
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Hello extends React.Component {
//这个功能是插件完成,使用需下载插件yarn add prop-types
static propTypes = {
//key:value
name:PropTypes.string //规定外部传入的属性值必须是字符串
}
static defaultProps = {
name:'默认名字' //自己设置外界传入属性的默认值
}
render(){
//this.props.name 进行接收
return (
<div>{this.props.name}</div>
)
}
(2)内部数据 - state - 组件内使用数据
定义: constructor里面定义
constructor(){
super();
//定义数据
this.state = {
name:'张三'
}
}
constructor外面定义:
state = {
name:'张三'
}
使用: this.state.name
修改:
this.setState({
name:'李四' //注意为异步操作
})
例子:
import React, { Component } from 'react'
export default Astate extends Component{
//state = {
// name:'张三'
//}
constructor(props){
super(props);
//定义数据
this.state = {
name:'张三'
}
}
//改为同步操作
// changeName = async ()=>{
// await this.setState({
// name:'李四'
// })
// }
changeName = ()=>{
//修改数据 - 异步方法
this.setState({
name:'李四'
},()=>{
//回调函数中可以获取到变化后的name值
})
}
console.log(this.state.name) //张三,setState是一个异步操作
render(){
return (
<div>
我是:{this.state.name}
<button onClik={changeName}>修改名字</button>
</div>
)
}
}
(3)refs属性
案例 - 点击显示输入框文本,失去焦点显示输入框文本
class ShowInput extends React.Component{
constructor(props){
super(props);
this.show = this.show.bind(this)
this.handBlur = this.handBlur.bind(this)
}
show () {
// alert(this.refs.content)
alert(this.input.value)
}
//事件处理函数
handBlur(e){
alert(this.e.target.value)
}
render(){
return ({
// <input type='text' ref = 'content'> 废弃的写法
<input type='text' ref = {input => this.input = input}>
<button onClik={this.show}>提示输入</button>
<input type='text' palceholder='失去焦点提示' onBlur ={this.handBlur}>
})
}
}
5.生命周期
(1)挂载阶段 -
//props表示外部传入的数据
constructor(props){
//初始化一些数据
}
componentWillMount(){
//通知数据已经初始化好了,可以进行界面渲染了
//不建议在这里发送接口,因为可能会执行多次
// == vue的created
}
render(){
//根据属性和状态渲染界面
return ()
}
componentDidMount(){
//通知组件已经挂载完成了 - 只会执行一次
//发送请求,获取Dom,设置定时器或者延时器
//== vue中的mounted
}
(2)运行阶段
1.state的改变
//状态改变是否要去更新界面,默认返回true,用于提升性能
shuoldComponentUpdate(){
return true
}
//新的数据已经准备好,可以渲染界面了
componentWillUpdate(){ }
//界面已经更新完了
componentDidUpdate(){}
2.prop的改变
//属性改变是否去更新界面
componentWillReceiveProps(newProps){
//newProps修改后的数据,this.props 以前的数据
console.log(newProps,this.props)
}
剩下和state一样
(3)卸载阶段
//通知组件即将销毁
componentWillUnmount(){
//清楚定时器延时器,解绑事件等等
}
生命周期图
5.表单组件
(1)不受控表单组件
import React, { Component } from 'react'
export default class NoCotron extends Component {
getValue = () =>{
//1.利用原生js获取
console.log(document.getElementById('input').value)
//2.所有的ref都是存储在this.refs中的 this.refs - 都是Dom元素
console.log(this.refs.inputs.value)
}
render() {
return (
<div>
<input type="text" id="input" ref='inputs'></input>
<button onClick={this.getValue}>获取text的值</button>
</div>
)
}
}
(6) 受控表单组件 - 表单的值是被当前的自定义的组件的状态控制起来 -让表单值与state关联起来
import React, { Component } from 'react'
export default class Control extends Component {
constructor(props) {
super();
this.state = {
vals: 'xx'
}
}
changeVal = (e) => {
this.setState({
vals: e.target.value
})
}
getValues = () => {
console.log(this.state.vals)
}
render() {
//利用value,onChange进行对数据绑定为动态数据 == vue的v-modle
return (
<div>
<input type="text" id="inputs" value={this.state.vals} onChange={this.changeVal}></input>
<button onClick={this.getValues}>获取text的值</button>
</div>
)
}
}
6.路由组件
下载路由插件 - yarn add react-router-dom@4.3.0
创建路由文件
import React, { Component } from 'react'
import { HashRouter, Switch, Route } from 'react-router-dom'
import Home from './Home'
import Login from './Login'
import Reg from './Reg'
import Error from './Error'
export default class Routes extends Component {
render() {
//注意: 从上到下,用了switch 后面会覆盖前面的
//HashRouter - 容器组件
//Switch 保证匹配到一个路劲就往下匹配
//path-标识当前路径 component-当前路径匹配的组件 exact - 精准匹配
return (
<HashRouter>
<Switch>
<Route path='/' exact component={Home}></Route>
<Route path='/login' component={Login}></Route>
<Route path='/reg' component={Reg}></Route>
<Route component={Error}></Route> 匹配所有的路径
</Switch>
</HashRouter>
)
}
}
路由跳转
跳转路由 - 标签跳转和js跳转
import {Link} from 'react-router-dom'
goToLogin = () =>{
//js的方法实现跳转
this.props.history.push('/login')
}
render(){
return(<Link to='/login'>跳转到1登陆</Link>)
}