Advertisement

手把手教你写react项目

阅读量:

1.创建项目

cnpm / npm i create-react-app -g
npx create-react-app myapp
在这里插入图片描述

2.抽离配置文件

cd myapp
运行 npm run eject 抽离配置文件
在这里插入图片描述
在这里插入图片描述修改package.json ,配置dev指令
在这里插入图片描述

3.配置项目

配置src文件夹的别名 @

pakeage.json的alias选项中:

复制代码
      'react-native': 'react-native-web',
      '@': path.join(__dirname,'../','src')

配置sass

npm i node-sass -D

4.项目基本结构

1.在App.js,创建样式基本结构

复制代码
    import React from 'react';
    function App() {
      return (
    <div className="container">
      <header className="header">header</header>
      <div className="content">cont</div>
      <footer className="footer">foot</footer>
    </div>
      );
    }
    
    export default App;

2.创建基本页面

在src新建各个页面
在这里插入图片描述
3.入口文件处引入相关文件并且配置

路由:
npm i react-router-dom -S

复制代码
    import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
    //给根节点root要通过路由去渲染页面,只有一个子元素switch
    ReactDOM.render(
    	<Router> 
    	<Switch>  
    		<Route path="/" component={App}/>
    	</Switch>
    	</Router>
    	, document.getElementById('root'));

4.app.js

复制代码
    import {Route,Switch} from 'react-router-dom';
    return (
    <div className="container">
    			<Switch>
    			<route path="/home" component={Home} />
    			<route path="/car" component={Car} />
    			<route path="/kind" component={Kind} />
    			<route path="/mine" component={Mine} />
    			</Switch>
      <footer className="footer">foot</footer>
    </div>
      );

但是什么都不输入的时候,不出效果 ------- 重定向

复制代码
    import {Route,Switch,Redirect} from 'react-router-dom';
    <Redirect to="/home"/>

5.底部布局,完成跳转

路由的跳转、声明式跳转

Link ---- 选中无效果
NavLink ---- 选中有效果

复制代码
    import {Route,Switch,Redirect, NavLink} from 'react-router-dom';
      <footer className="footer">
      <ul>
      <NavLink to="/home">首页</NavLink>    //会被转成a标签,设置样式选中a标签
      <NavLink to="/kind">分类</NavLink>    //选中的会有一个class=active类
      <NavLink to="/car">购物车</NavLink>
      <NavLink to="/mine">我的</NavLink>
      </ul>
      </footer>

5.请求数据

父组件给子组件传值:在父组件调用子组建的地方添加一个自定义的属性,属性的值就是你要传的值,如果值是一个变量就用到大括号,在定义子组件的地方,如果子组件是一个函数式组件,默认的参数点属性名就是传递的值,如果是类组件,this.props.属性名就是传过来的值。

src新建components文件,中Prolist组件

复制代码
    import React from 'react'
    export default (props)=>{
    	return (
    		<ul>
    		{
    			props.prolist.map((item,index)=>(
    				<li key={index}>{item.title}</li>
    			))
    		}
    		</ul>
    	)
    }

在父组件请求数据:

复制代码
    	componentDidMount(){
    		axios.get('https://www.daxunxun.com/douban').then(res=>{
    			this.setState({
    				prolist:res.data
    			})
    		})
    	}
    	render(){
    		return (
    		<div className="box">
    		<header className="header">header</header>
    		<div className="content">
    		<Prolist prolist={this.state.prolist}/>
    		</div>
    		</div>
    		)
    	}

6.构建详情页面

入口找布局,布局找页面,页面找组件

默认布局和页面可以通过this.props访问路由,默认组件不能直接访问,如果想要组件访问路由,在调用该组件的地方传一个{…this.props}

在index.js中找app布局或者detail布局,在app.js中找页面
新建一个布局other.js,此时有两个布局文件,还有一个是APP.JS

复制代码
    <Switch>
    <Route path="/detail" component={ Detail }/>
    </Switch>

创建路由:在index.js,

复制代码
    import Detail from '@/otherApp'
    	<Switch> 
    	  <Route path = "/other" component={ OtherApp }/>
    		<Route path = "/" component={ App }/>
    	</Switch>

但是当你放入login时,就会重定向了
在detailApp中,前边加上detail/login 就可以了

复制代码
    <Switch>
    <Route path="/other/login" component={ Login }/>
    <Route path="/other/detail" component={ Detail }/>
    </Switch>

7.跳转详情页面

1.声明式跳转

在prolist组件中:
传值:在otherApp中: 加上/:id

复制代码
    <Route path="/other/detail/:id" component={ Detail }/>

在prolist组件:

复制代码
    import React from 'react'
    import {Link} from 'react-router-dom'
    export default (props)=>{
    	return (
    		<ul>
    		{
    			props.prolist.map((item,index)=>(
    				<Link to={ "/other/detail/" + item.id } key={index}>{item.title}</Link> //遇到变量就腰用到{}
    			))
    		}
    		</ul>
    	)
    }

详情页去获取数据

复制代码
    import React , {Component} from 'react'
    import axios from 'axios'
    export default class extends Component {
    	constructor(props){
    		super(props)
    		this.state={
    			title:''
    		}
    	}
    	componentDidMount(){
    		const {props:{match:{params:{id}}}} =this
    		axios.get('https://www.daxunxun.com/detail?id='+id).then(res=>{
    			this.setState({
    				title:res.data[0].title
    			})
    		})
    	}
    	render(){
    		return (
    			<div className="box">
    				<header className="header">header</header>
    				<div className="content">
    				{this.state.title}
    				</div>
    			</div>
    		)
    	}
    }

2.编程式跳转

默认布局和页面可以通过this.props访问路由,默认组件不能直接访问,如果想要组件访问路由,在调用该组件的地方传一个{…this.props}

复制代码
    <Prolist prolist={this.state.prolist}{...this.props}/>

在组件中

复制代码
    import React from 'react'
    export default (props)=>{
    	return (
    		<ul>
    		{
    			props.prolist.map((item,index)=>(
    				<li key={index} onClick={()=>{
    					props.history.push('/other/detail/' + item.id)
    					//repalce goback
    					}}>
    					{item.title}
    				</li>
    			))
    		}
    		</ul>
    	)
    }

8.重定向遇到404

复制代码
    	<Redirect from="/" exact to="/home"/> //只有当重定向是/才会重定向到home

编写一个404页面

9.UI库使用 antd-mobile

https://mobile.ant.design/docs/react/introduce-cn

安装依赖
npm install antd-mobile --save

FastClick
Pc端使用的是click事件,移动端如果也使用click事件,会发生“点击穿透”的现象(手机网页 双击屏幕 会放大页面,点击事件延迟300ms — 移动端补充章节)

复制index.html
自动引入:

10.状态管理器

11.反向代理

12.mock模拟数据

13.diff算法

render 执行的结果得到的不是真正的 DOM 节点.结果仅仅是轻量级的 JavaScript 对象, 我们称之为 virtual DOM—虚拟DOM

diff算法:操作dom时只会去改变变化的地方,根据标签的层级从外向内查找变化的地方标签存在则复用标签,不存在就创建虚拟dom:react中的render方法就是虚拟的dom
在遍历时加一个key

14.受控组件和非受控组件

15.token

16.hook

特殊的函数,使用hook可在函数式组件中使用状态,使用useState唯一的参数初始值,在定义的方法中修改状态
可在函数式组件中使用状态

  1. 声明一个新的叫做 “count” 的 state 变量,此处使用 [], 不能使用 {}
复制代码
    const Com = () => {
      // 声明一个新的叫做 “count” 的 state 变量,此处使用 [], 不能使用 {}
      const [ count, setCount ] = useState(1)
      return (
    <div>
      <button onClick = { () => {
        let a = count + 1
        setCount(a)
      }}>+1</button>
      { count }
    </div>
      )
    }
    
    export default Com

2.useEffect
副作用,若有数据请求会一直执行

复制代码
    import React, { useState, useEffect } from 'react'
    import axios from 'axios'
    // 使用 HOOK useState 可以在 函数式组件 中 用状态
    const Com = () => {
      // 声明一个新的叫做 “count” 的 state 变量,此处使用 [], 不能使用 {}
      const [ count, setCount ] = useState(1)
      const [ bannlist, setBannerlist ]= useState([])
      useEffect(() => {
    axios.get('https://www.daxunxun.com/banner').then(res => {
      setBannerlist(res.data)
    })
      })
      return (
    <div>
      <button onClick = { () => {
        let a = count + 1
        setCount(a)
      }}>+1</button>
      { count }
      <ul>
        { 
          bannlist.map((item, index) => (
            <li key = { index }> { item }</li>
          ))
        }
      </ul>
    </div>
      )
    }
    
    export default Com

性能优化
只请求一次,清除上一次,创建下一次。后加[ ] ,不会再触发,
usecontext
useReducer是useState的替代,只能针对本组件。

ref

获取所有节点,函数组件不可用ref
console.log(this.refs)
类组件this.refs.refs获取dom节点

react的插槽

复制代码
    export default (props) => {
      return (
    <header>
      { props.children }
    </header>
      )
    }
    //在调用的地方
      <Header>
        <div className="left">左</div>
        <div className="center">中</div>
        <div className="right">右</div>
      </Header>

高阶组件
高阶组件HOC,复用组件的逻辑,组件作为一个参数返回一个新的 参数
解决HOC解决横切关注点问题,until接受参数(com,data),在组件中until。connect(传一个组件和数据)
虚拟化长列表,利用滚动技术,react-window模块,返回顶部

mobx状态管理

全家桶
vue
vue + vue-router + axios/fetch + vuex + mint-ui/vant/element-ui/iview

ES7语法:装饰器
是一个函数,可装饰类或类中的成员
举例:object.fefineproperty( )
indexstore

复制代码
    import HomeStore from "./home";
    import KindStore from "./kind";
    class Store {
      constructor () {
    this.home = new HomeStore(this);
    this.kind = new KindStore(this);
      }
    }
    
    export default new Store()
复制代码
    import { observable, action } from 'mobx'
    
    class HomeStore {
      @observable bannerlist = []
    
      @observable prolist = []
    
      constructor (store) {
    this.store = store
    this.changeBannerlist = this.changeBannerlist.bind(this)
    this.changeProlist = this.changeProlist.bind(this)
      }
    
      @action
      changeBannerlist (data) {
    this.bannerlist = data
      }
      @action
      changeProlist (data) {
    this.prolist = data
      }
    }
    
    export default HomeStore
复制代码
    import axios from 'axios'
    @inject('store')
    @observer
    class Com extends Component {
      constructor (props) {
    super(props)
    this.state = {}
      }
      componentDidMount () {
    axios.get('https://www.daxunxun.com/banner').then(res => {
      this.props.store.home.changeBannerlist(res.data)
    })
      }

全部评论 (0)

还没有任何评论哟~