使用create-react-app创建react脚手架

一、 react脚手架 


项目的整体技术架构为:  react + webpack + es6 + eslint
参考网址 :https://zhuanlan.zhihu.com/p/299208218

##  一  react脚手架安装项目
    1.  npm i -g create-react-app      // 全局安装create-react-app库,用来创建react脚手架项目的库,查看是否安装可以通过create-react-app  -v 或者 npm root -a  得到一个路径,通过路径查看全局安装了什么包

    2.  create-react-app  hello-react  // 通过creat-react-app 安装脚手架 ,"hello-react"为项目名称,可以自己定义
    3.  cd hello-react    // 进入项目文件夹
    4.  npm start    // 启动项目
## 二  脚手架 下载下来的文件结构

    public ---- 静态资源文件夹
		favicon.icon ------ 网站页签图标
		index.html -------- 主页面
		logo192.png ------- logo图
		logo512.png ------- logo图
		manifest.json ----- 应用加壳的配置文件
		robots.txt -------- 爬虫协议文件
    src ---- 源码文件夹
		App.css -------- App组件的样式
		App.js --------- App组件
		App.test.js ---- 用于给App做测试
		index.css ------ 样式
		index.js ------- 入口文件
		logo.svg ------- logo图
		reportWebVitals.js
			--- 页面性能分析文件(需要web-vitals库的支持)
		setupTests.js
			---- 组件单元测试的文件(需要jest-dom库的支持)
## 三 脚手架删除多余的文件

    public ---- 静态资源文件夹
        index.html -------- 主页面
    src ---- 源码文件夹
        components -------- 存放组件的文件夹
        App.js --------- App组件
        index.js ------- 入口文件
    package.json ------- 项目的配置信息,安装包信息 
    package-lock.json ------- 通过npm isntall 安装package.json里所有包,并将包及它的所有依赖项保存进package-lock.json
    yarn.lock ------  通过yarn install安装package.json里所有包,并将包及它的所有依赖项保存进yarn.lock,有此文件会锁住包的版本 【需要注意一点,如果通过yarn add 来安装包,你之后通过package.json文件安装所有包的时候请使用 yarn install 】

## 四 配置antd按需映入,主题自定义,配置装饰器

     1.  安装基本依赖:
            antd : 蚂蚁金服UI库,
            @craco/craco :通过此插件修改webpack,
            @babel/plugin-proposal-decorators :配置装饰器的库,
            babel-plugin-import :按需引入的库
            craco-less :自定义主题需要用到类似 less-loader 提供的 less 变量覆盖功能,我们可以引入 craco-less 来帮助加载 less 样式和修改变量

         安装命令:yarn add antd @craco/craco craco-less @babel/plugin-proposal-decorators babel-plugin-import 
     2.修改 package.json 中的 scripts

         {
          "scripts":{
                    "start": "set PORT=5000 && craco start FAST_REFRESH=true",
                    "build": "set GENERATE_SOURCEMAP=false && craco build",
                    "analyzer": "env NODE_ENV=production BUILD_ANALYZER=true yarn start",
                    "test": "craco test"
                    }
         }

      2.1)  修改 package.json 中的package.json -> eslintConfig ->rules ->
                //配置 eslint 去掉 no-unused-vars 报错
                {
	              // "no-": "off",
                  //"no-debugger":"off",
                  //"no-console": "off",
                  //"no-empty":"off",
                  "no-unused-vars":"off" 
                }
        

     3.  在项目根目录(src同级)创建一个 craco.config.js 用于修改默认配置

     4.  craco.config.js中的配置

        const CracoLessPlugin = require('craco-less');
        module.exports = {
            babel: {
                    plugins: [
                        ['import', { libraryName: 'antd', style: true }],  //按需引入
                        ['@babel/plugin-proposal-decorators', { legacy: true }]  // 装饰器配置
                    ]
                },
            plugins: [
                        {
                            plugin: CracoLessPlugin,
                            options: {
                                // 此处根据 less-loader 版本的不同会有不同的配置,详见 less-loader 官方文档
                                lessLoaderOptions: {
                                    lessOptions: {
                                        //modifyVars: { '@primary-color': '#23442232' },   // 更改主题颜色
                                        javascriptEnabled: true
                                    }
                                }
                            }
                        }
                    ]
        };
    

二、 react-router-dom

## 一、路由的基本使用
			1.明确好界面中的导航区、展示区
			2.导航区的a标签改为Link标签
						<Link to="/xxxxx">Demo</Link>
			3.展示区写Route标签进行路径的匹配
						<Route path='/xxxx' component={Demo}/>
			4.<App>的最外侧包裹了一个<BrowserRouter>或<HashRouter>

## 二、路由组件与一般组件
			1.写法不同:
						一般组件:<Demo/>
						路由组件:<Route path="/demo" component={Demo}/>
			2.存放位置不同:
						一般组件:components
						路由组件:pages
			3.接收到的props不同:
						一般组件:写组件标签时传递了什么,就能收到什么
						路由组件:接收到三个固定的属性
											history:
														go: ƒ go(n)
														goBack: ƒ goBack()
														goForward: ƒ goForward()
														push: ƒ push(path, state)
														replace: ƒ replace(path, state)
											location:
														pathname: "/about"
														search: ""
														state: undefined
											match:
														params: {}
														path: "/about"
														url: "/about"

## 三、NavLink与封装NavLink
				1.NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
                2.<NavLink to='/xx/xx'>Home</NavLink> 相当于 <NavLink to='/xx/xx' children={'Home'}/>

## 四、Switch的使用
				1.通常情况下,path和component是一一对应的关系。
				2.Switch可以提高路由匹配效率(单一匹配)。

## 五、解决多级路径刷新页面样式丢失的问题
				1.public/index.html 中 引入样式时不写 ./ 写 / (常用)
				2.public/index.html 中 引入样式时不写 ./ 写 %PUBLIC_URL% (常用)
				3.使用HashRouter

## 六、路由的严格匹配与模糊匹配
				1.默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
				2.开启严格匹配:<Route exact={true} path="/about" component={About}/>
				3.严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由

## 七、Redirect的使用	
				1.一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路                
                由
				2.具体编码:
						<Switch>
							<Route path="/about" component={About}/>
							<Route path="/home" component={Home}/>
							<Redirect to="/about"/>
						</Switch>

## 八、嵌套路由
				1.注册子路由时要写上父路由的path值
				2.路由的匹配是按照注册路由的顺序进行的

## 九、向路由组件传递参数
				1.params参数
							路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
							注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
							接收参数:this.props.match.params
				2.search参数
							路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
							注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
							接收参数:this.props.location.search
							备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
				3.state参数
							路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
							注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
							接收参数:this.props.location.state
							备注:刷新也可以保留住参数
				


## 十、编程式路由导航
					借助this.prosp.history对象上的API对操作路由跳转、前进、后退
							-this.props.history.push()
							-this.props.history.replace()
							-this.props.history.goBack()
							-this.props.history.goForward()
							-this.props.history.go()

## 十一、BrowserRouter与HashRouter的区别
			1.底层原理不一样:
						BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
						HashRouter使用的是URL的哈希值。
			2.path表现形式不一样
						BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
						HashRouter的路径包含#,例如:localhost:3000/#/demo/test
			3.刷新后对路由state参数的影响
						(1).BrowserRouter没有任何影响,因为state保存在history对象中。
						(2).HashRouter刷新后会导致路由state参数的丢失!!!
			4.备注:HashRouter可以用于解决一些路径错误相关的问题。
## 十二、withRouter的使用
            1. 是一般组件装换成路由组件,withRouter是一个函数
            2. 使用:
                    import {withRouter} from 'react-router-dom'   
                    export default withRouter(<一般组件名称>)
            3. 包装之后的组件里会有同路由组件一样多了很多路由专属的API可用(this.props)
    // 路由使用得基本结构  to,path和component是一一对应的关系

    <BrowserRouter> // 路由器的两种表现形式 BrowserRouter 和 HashRouter
            <ul>
                    <li><NavLink to='/about/tom'>tom</NavLink></li>
                    <li><NavLink to='/about/bill'>bill</NavLink></li>
                    <li><NavLink to='/about/alex'>alex</NavLink></li>
            </ul>
            <div>
                    <Switch> // Switch可以提高路由匹配效率,匹配到路由就不会继续匹配下去
                        <Route exact path='/about/tom' component={Tom} />  //exact 精准匹配路由
                        <Route path='/about/bill' component={Bill} />
                        <Route path='/about/alex' component={Alex} />
                    </Switch>

            </div>
    </BrowserRouter>

  ## 路由传参有三种方法
            1.params参数
							路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
							注册路由(声明接收):<Route path="/demo/test/:name/:age"                 
                                                                 component={Test}/>
							接收参数:this.props.match.params
				2.search参数
							路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
							注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
							接收参数:this.props.location.search
							备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
				3.state参数
							路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
							注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
							接收参数:this.props.location.state
							备注:刷新也可以保留住参数(只的是BrowserRouter路由)
       
        

三、redux

// 安装 redux , react-redux 

   yarn add redux  react-redux  // 默认是安装在生产环境(-S)
   yarn add redux-thunk    //  中间件 允许异步action,就是指action的值为函数

    redux主要由三部分组成:store,reducer,action
    store是一个对象,它有四个主要的方法(dispatch,subscribe,getState,replaceReducer)
    reducer


1.  创建一个store,应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中,
    store可以通过createStore()方法创建,接受三个参数,经过combineReducers合并的reducer和                            state的初始状态以及改变dispatch的中间件,后两个参数并不是必须的。store的主要作用是将action和                reducer联系起来并改变state

    import { createStore, combineReducers } from "redux"
    import aboutReducer from "../reducers/aboutReducer" // reducers 处理简单逻辑返回的是一个函数
    import homeReducer from "../reducers/homeReducer"  // reducers 处理简单逻辑返回的是一个函数

    const allReducers = combineReducers({
    aboutData: aboutReducer,
    homeData: homeReducer
    })

    export default createStore(allReducers)

2.  容器组件需要包裹UI组件,UI组件和容器组件通过react-redux中的connect()相互连接,
    UI组件可以直接通过this.props直接获取数据, connect()接受两个参数并且还是函数,

    第一个函数(mapStateToProps)返回的是一个对象,对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value,该函数用于传递状态

	第二个函数(mapDispatchToProps)函数返回的是一个对象,返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value,该函数用于传递操作状态的方法

    connect(
        state => {
            return { modal: state }
        },
        dispatch => ({
            jia: number => dispatch({ type: 'jia', data: number })
        })

    )(About) // About是UI组

3. React-Redux 提供<Provider/>组件,能够使整个app访问到Redux store中的数据

    ReactDOM.render(
	    <Provider store={store}>
		    <App/>
	    </Provider>,
	    document.getElementById('root')
    )


##总结   
    
     1. 创建一个store.js文件, 引入reducers, 例子 :
        
        // store.js 该文件专门用于暴露一个store对象,整个应用只有一个store对象
        
        //引入createStore,专门用于创建redux中最为核心的store对象

            import {createStore,applyMiddleware} from 'redux' 

        //引入redux-thunk,用于支持异步action

            import thunk from 'redux-thunk'

        //暴露store 

            export default createStore(reducer,applyMiddleware(thunk))

      2. 在入口文件引入 store.js, 
        
        // index.js

            import React from 'react'
            import ReactDOM from 'react-dom'
            import App from './App'
            import store from './redux/store'
            import {Provider} from 'react-redux'

        
           ReactDOM.render(
	           /* 此处需要用Provider包裹App,目的是让App所有的后代容器组件都能接收到store */
	            <Provider store={store}>
		            <App/>
	            </Provider>,
	        document.getElementById('root')
           )

       3. 在UI组件中,此时UI组件命名为Home

            import React, { Component } from 'react'
            //引入connect用于连接UI组件与redux
            import {connect} from 'react-redux'

        //定义UI组件
        class Home extends Component { 
            render(){
                return <div> ..... </div>
            }
              
         } 
        //使用connect()()创建并暴露一个Count的容器组件
    export default connect(
	    state => ({
		        count:state.count,
		        personCount:state.persons.length
	        }),
	        {increment,decrement,incrementAsync}
        )(Home)

             









       

四、Hooks

(1). Hook是React 16.8.0版本增加的新特性/新语法
(2). 可以让你在函数组件中使用 state 以及其他的 React 特性

三个常用的Hook : State Hook 、Effect Hook 、Ref Hook

## State Hook

(1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作
(2). 语法: const [xxx, setXxx] = React.useState(initValue)  
(3). useState()说明:
        参数: 第一次初始化指定的值在内部作缓存
        返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
(4). setXxx()2种写法:
        setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
        setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值

const  [count,setCount] = React.useState(init) 

    count : 初始变量

    setCount :更新变量 

            写法1:setCount(count+1)

            写法2 : setCount(count => count+1)

    init : 初始值


## Effect Hook

(1). Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
(2). React中的副作用操作:
        发ajax请求数据获取
        设置订阅 / 启动定时器
        手动更改真实DOM
(3). 语法和说明: 
        useEffect(() => { 
          // 在此可以执行任何带副作用操作
          return () => { // 在组件卸载前执行
            // 在此做一些收尾工作, 比如清除定时器/取消订阅等
          }
        }, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
    
(4). 可以把 useEffect Hook 看做如下三个函数的组合
        componentDidMount()
        componentDidUpdate()
    	componentWillUnmount()

React.useEffect(()=>{})   // 相当于类组件中 componentDidMount , componentWillUpdate

React.useEffect(()=>{},[])  // 相当于 componentDidMount 

React.useEffect(()=>{},[Name])  // 当setName的时候,会触发 

React.useEffect(()=>{ return ()=>{} },[Name])  // 返回函数的函数相当于componentWillUnmount

## Ref  Hook

(1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
(2). 语法: const refContainer = useRef()
(3). 作用:保存标签对象,功能与React.createRef()一样

例子:
function Demo(){
    
    const myRef = React.useRef()

   	function show(){
		alert(myRef.current.value)
	}
    return (
        <div>
              <input type="text" ref={myRef}/>
              <button onClick={show}>点我提示数据</button>
        <div>
    )
}
 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值