官方脚手架

安装

npm方式

npm install -g create-react-app
create-react-app my-app

npx方式

npx create-react-app my-app

临时安装 create-react-app 包,安装完成后create-react-app 包会删除,不会像npm install -g create-react-app全局安装占用空间,两种方式会使用yarn进行安装

安装完成按照提示操作即可

npx安装
cd my-app //项目名称
yarn start //运行项目
yarn //安装依赖

使用案例

ant design是阿里旗下UI,下面引入 antd-mobile进行案例编写

npx方式创建的项目结构,并添加components文件夹存放jsx后缀组件,组件内容复制于antd-mobile

在该文件目录下执行
npm install react-app-rewired --save-dev
npm install antd-mobile 或 yarn add antd-mobile

index.js中添加语句

index.js
//全局样式
import 'antd-mobile/dist/antd-mobile.css';

Xheader.jsx组件

import React, { Component } from 'react';
import { NavBar, Icon } from 'antd-mobile';export default class Xheader extends Component {render() {return (<div><NavBarmode="light"icon={<Icon type="left" />}onLeftClick={() => console.log('onLeftClick')}rightContent={[<Icon key="0" type="search" style={{ marginRight: '16px' }} />,<Icon key="1" type="ellipsis" />,]}>NavBar</NavBar></div>);}
}

Xsearch.jsx组件

import React, { Component } from 'react';
import { SearchBar} from 'antd-mobile';export default class Xsearch extends Component {componentDidMount() {this.autoFocusInst.focus();}onChange= (value) => {this.setState({ value });};clear = () => {this.setState({ value: '' });};handleClick = () => {this.manualFocusInst.focus();}render() {return (<div><SearchBar placeholder="自动获取光标" ref={ref => this.autoFocusInst = ref} /></div>);}
}

Xtab.jsx组件

import React, { Component } from 'react';
import { Tabs, WhiteSpace, Badge } from 'antd-mobile';const tabs = [{ title: <Badge text={'3'}>First Tab</Badge> },{ title: <Badge text={'今日(20)'}>Second Tab</Badge> },{ title: <Badge dot>Third Tab</Badge> },
];const tabs2 = [{ title: 'First Tab', sub: '1' },{ title: 'Second Tab', sub: '2' },{ title: 'Third Tab', sub: '3' },
];export default class Xtab extends Component {render() {return (<div><Tabs tabs={tabs}initialPage={1}onChange={(tab, index) => { console.log('onChange', index, tab); }}onTabClick={(tab, index) => { console.log('onTabClick', index, tab); }}><div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '150px', backgroundColor: '#fff' }}>Content of first tab</div><div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '150px', backgroundColor: '#fff' }}>Content of second tab</div><div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '150px', backgroundColor: '#fff' }}>Content of third tab</div></Tabs> </div>);}
}

App.js进行修改

App.js
import React, { Component } from 'react';
import Xheader from './components/Xheader';
import Xsearch from './components/Xsearch';
import Xtab from './components/Xtab';
import './App.css';class App extends Component {render() {return (<div className="App"><Xheader /><Xsearch /><Xtab /></div>);}
}export default App;

执行yarn start,看到效果

脚手架中搭建路由

用官方脚手架搭建路由实现单页面跳转
react-router网址

一层路由

创建脚手架
npx create-react-app katsuki-app安装依赖
yarn安装react-router-dom模块
npm install react-router-dom --save

katsuki-app创建完成后,添加放公有组件的components文件夹和放路由组件的pages文件夹pages文件夹中添加Home.jsxKatsuki.jsx

Home.jsx
import React,{Component} from 'react';export default class Home extends Component{constructor(props){super(props);this.props = props;}render(){return (<div>Home Page</div>)  }
}
Katsuki.jsx
import React,{Component} from 'react';export default class Katsuki extends Component{constructor(props){super(props);this.props = props;}render(){return (<div>Katsuki Page</div>)}
}

修改App.js文件
路由补充:react-routerv4版本中,如匹配 path="/katsuki"的路由会匹配 path="/"的路由,路由会包含匹配,在页面中这两个模块会同时进行渲染。添加exact关键词,表示只对当前的路由进行匹配。

App.js
import React, { Component } from 'react';
// 路由模块提供了三个组件
// Router路由的容器 相当于vue的<router-view>标签
// Route是要放在Router组件里面的,用来定义路由规则
// Link相当于a标签,用来声明式导航,你可以用JS的编程式导航取代
import { HashRouter as Router, Route, Link } from "react-router-dom";
import './App.css';
import Home from './pages/Home';
import Katsuki from './pages/Katsuki.jsx'class App extends Component {render() {return ({/* 注释也是一个标签,放在这里(最外层父组件外)会出错 */}<Router>{/* 最外层需要用Router组件包裹 */}<div className="App"><ul><li><Link to="/">Home</Link></li><li><Link to="/katsuki">Katsuki</Link></li></ul>{/*如果匹配到* / 那在这里加载 Home组件*/}<Route exact path="/" component={Home}  />{/*如果匹配到* /katsuki 那在这里加载 Katsuki组件*/}<Route path="/katsuki" component={Katsuki}  /></div></Router>);}
}export default App;

至此yarn start,实现一层路由效果

嵌套路由(二层路由)
在上面的基础上,pages文件夹中添加Katsuki文件夹Katsuki文件夹中添加Oulaoula.jsxMudamuda.jsx

Oulaoula.jsx
// Component as C 重命名
import React, { Component as C } from 'react';
export default class Oulaoula extends C {constructor(props) {super(props)// 因为Oulaoula是被Route组件给调用的,所以会在它的props下面拥有三个值(match,history,location)this.props = props}toHomePage(){// 编程式导航this.props.history.push('/')// 编程式导航本质上就是对location方法的封装// location.href}render() {return (<div>Oulaoula Pages<p>传进来的值{this.props.match.params.id}</p><button onClick={this.toHomePage.bind(this)}>编程式导航</button></div>)}
}
Mudamuda.jsx
import React, { Component } from 'react';export default class Mudamuda extends Component {constructor(props) {super(props)this.props = props}render() {return (<div>Mudamuda Pages</div>)}
}

Katsuki.jsx进行修改

Katsuki.jsx
import React, { Component } from 'react';
import { Route, Link } from "react-router-dom";
import Oulaoula from "./Katsuki/Oulaoula.jsx";
import Mudamuda from "./Katsuki/Mudamuda.jsx";export default class Katsuki extends Component {constructor(props) {super(props)this.props = propsthis.state = {id: 1}}getInputValue(e){this.setState({id: e.target.value})}render() {return (<div>Katsuki Page{/* 变更this.state.id值输入框 */}<input value={this.state.id} onChange={this.getInputValue.bind(this)}/><ul><li>{/* 带参数路由 */}<Link to={`/katsuki/oulaoula/${this.state.id}`}>Oulaoula</Link></li><li><Link to="/katsuki/mudamuda">Mudamuda</Link></li></ul>{/* 带参数路由 */}<Route path="/katsuki/oulaoula/:id" component={Oulaoula} /><Route path="/katsuki/mudamuda" component={Mudamuda} /></div>)}
}

至此yarn start,实现二层路由效果

dva脚手架

安装

npm install dva-cli -g   全局安装
dva new dva-quickstart   创建应用进入运行
cd dva-quickstart
npm start

安装完成的项目结构

文件夹/文件 描述
components 放公有组件,即不同页面复用组件
routes 放页面组件
assets 放静态资源
models 相当于Vuex,放数据文件
services 放复用方法文件
utils 放封装库,内有ajax的封装文件
mock 放模拟数据,如静态json文件
public 放html页面
index.css 全局样式
index.js 主js文件
router.js 路由文件

引入antd

下面引入 antd进行案例编写,教程可看DvaJS文档,下面是其部分内容

使用前进行下列安装配置

安装antd
npm install antd --save
安装antd样式引入处理插件,实现按需加载
npm install antd babel-plugin-import --save

index.js中引入样式

import 'antd/dist/antd.css';  //'antd/dist/antd.less'

编辑.webpackrc,使 babel-plugin-import 插件生效,添加下列语句

{"extraBabelPlugins": [["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]]
}

使用antd

src文件夹下添加layout文件夹,里面添加一个Layout.jsx,也要将index.css的内容清空

Layout.jsx
import React, { Component } from 'react';
import {Layout, Menu, Breadcrumb, Icon,} from 'antd';const { SubMenu } = Menu;
const { Header, Content, Sider } = Layout;class GlobalLayout extends Component {state = {collapsed: false,};toggle = () => {this.setState({collapsed: !this.state.collapsed,});}render() {return (<Layout><Header className="header"><div className="logo" /><Menutheme="dark"mode="horizontal"defaultSelectedKeys={['2']}style={{ lineHeight: '64px' }}><Menu.Item key="1">katsuki</Menu.Item><Menu.Item key="2">kasami</Menu.Item><Menu.Item key="3">Grisaia</Menu.Item></Menu></Header><Layout><Sider width={200} style={{ background: '#fff' }}><Menumode="inline"defaultSelectedKeys={['1']}defaultOpenKeys={['sub1']}style={{ height: '100%', borderRight: 0 }}><SubMenu key="sub1" title={<span><Icon type="user" />subnav 1</span>}><Menu.Item key="1">option1</Menu.Item><Menu.Item key="2">option2</Menu.Item><Menu.Item key="3">option3</Menu.Item><Menu.Item key="4">option4</Menu.Item></SubMenu><SubMenu key="sub2" title={<span><Icon type="laptop" />subnav 2</span>}><Menu.Item key="5">option5</Menu.Item><Menu.Item key="6">option6</Menu.Item><Menu.Item key="7">option7</Menu.Item><Menu.Item key="8">option8</Menu.Item></SubMenu><SubMenu key="sub3" title={<span><Icon type="notification" />subnav 3</span>}><Menu.Item key="9">option9</Menu.Item><Menu.Item key="10">option10</Menu.Item><Menu.Item key="11">option11</Menu.Item><Menu.Item key="12">option12</Menu.Item></SubMenu></Menu></Sider><Layout style={{ padding: '0 24px 24px' }}><Breadcrumb style={{ margin: '16px 0' }}><Breadcrumb.Item>Home</Breadcrumb.Item><Breadcrumb.Item>List</Breadcrumb.Item><Breadcrumb.Item>App</Breadcrumb.Item></Breadcrumb><Content style={{background: '#fff', padding: 24, margin: 0, minHeight: 280,}}>Content</Content></Layout></Layout></Layout>);}
}export default GlobalLayout

修改routes文件夹下的IndexPage.js

IndexPage.js
import React from 'react';
import { connect } from 'dva';
// import styles from './IndexPage.css';
import Layout from '../layout/Layout.jsx'function IndexPage() {return (<div><Layout /></div>);
}IndexPage.propTypes = {};export default connect()(IndexPage);

到此执行npm start可看到运行效果

配置dva路由

一层路由
routes文件夹中的页面组件:创建Katsuki.jsGrisaia.js,修改IndexPage.js

IndexPage.js
import React from 'react';
import { connect } from 'dva';
import Xheader from '../components/Xheader.jsx';function IndexPage() {return (<div><Xheader menu="1"/></div>);
}IndexPage.propTypes = {};export default connect()(IndexPage);
Katsuki.js
import React from 'react';
import { connect } from 'dva';
import Xheader from '../components/Xheader.jsx';
import Xcontent from '../components/Xcontent.jsx';function KatsukiPage() {return (<div><Xheader menu="2"/><Xcontent /></div>);
}KatsukiPage.propTypes = {};export default connect()(KatsukiPage);
Grisaia.js
import React from 'react';
import { connect } from 'dva';
import Xheader from '../components/Xheader.jsx';function GrisaiaPage() {return (<div><Xheader menu="3"/></div>);
}GrisaiaPage.propTypes = {};export default connect()(GrisaiaPage);

抽离Layout.jsx的头部和中间部分,在components文件夹中分别创建Xheader.jsxXcontent.jsx作为复用组件

Xheader.jsx
import React,{Component} from 'react';
import {Layout, Menu} from 'antd';const { Header } = Layout;class XHeader extends Component {constructor(props){super(props);this.props = props}// 路由跳转方法toMenu(menu){this.setState({menu})let menus = {'1' : '#/','2' : '#/katsuki','3' : '#/grisaia'}window.location.href = menus[menu]}render(){return(<Header className="header"><div className="logo" /><Menutheme="dark"mode="horizontal"// 根据赋予的值对应下方Menu.Item的key值高亮// 根据父级组件传入的menu赋值defaultSelectedKeys={[this.props.menu]}style={{ lineHeight: '64px' }}><Menu.Item onClick={this.toMenu.bind(this,'1')} key="1">kasami</Menu.Item><Menu.Item onClick={this.toMenu.bind(this,'2')} key="2">katsuki</Menu.Item><Menu.Item onClick={this.toMenu.bind(this,'3')} key="3">Grisaia</Menu.Item></Menu></Header>)}
}export default XHeader
Xcontent.jsx
import React, { Component } from 'react';
import {Layout, Menu, Breadcrumb, Icon,
} from 'antd';const { SubMenu } = Menu;
const { Content, Sider } = Layout;class Xcontent extends Component {state = {collapsed: false,};toggle = () => {this.setState({collapsed: !this.state.collapsed,});}render() {return (<Layout><Sider width={200} style={{ background: '#fff' }}><Menumode="inline"defaultSelectedKeys={['1']}defaultOpenKeys={['sub1']}style={{ height: '100%', borderRight: 0 }}><SubMenu key="sub1" title={<span><Icon type="user" />subnav 1</span>}><Menu.Item key="1">option1</Menu.Item><Menu.Item key="2">option2</Menu.Item><Menu.Item key="3">option3</Menu.Item><Menu.Item key="4">option4</Menu.Item></SubMenu><SubMenu key="sub2" title={<span><Icon type="laptop" />subnav 2</span>}><Menu.Item key="5">option5</Menu.Item><Menu.Item key="6">option6</Menu.Item><Menu.Item key="7">option7</Menu.Item><Menu.Item key="8">option8</Menu.Item></SubMenu><SubMenu key="sub3" title={<span><Icon type="notification" />subnav 3</span>}><Menu.Item key="9">option9</Menu.Item><Menu.Item key="10">option10</Menu.Item><Menu.Item key="11">option11</Menu.Item><Menu.Item key="12">option12</Menu.Item></SubMenu></Menu></Sider><Layout style={{ padding: '0 24px 24px' }}><Breadcrumb style={{ margin: '16px 0' }}><Breadcrumb.Item>Home</Breadcrumb.Item><Breadcrumb.Item>List</Breadcrumb.Item><Breadcrumb.Item>App</Breadcrumb.Item></Breadcrumb><Content style={{background: '#fff', padding: 24, margin: 0, minHeight: 280,}}>Content</Content></Layout></Layout>);}
}export default Xcontent

修改router.js

import React from 'react';
import { Router, Route, Switch } from 'dva/router';
import IndexPage from './routes/IndexPage.js';
import KatsukiPage from './routes/Katsuki.js';
import GrisaiaPage from './routes/Grisaia.js';function RouterConfig({ history }) {return (<Router history={history}><Switch><Route path="/" exact component={IndexPage} /><Route path="/katsuki" exact component={KatsukiPage} /><Route path="/grisaia" exact component={GrisaiaPage} /></Switch></Router>);
}export default RouterConfig;

到此npm start,实现一层路由效果

当前antd布局侧边栏切换内容效果
components文件夹中创建SubNav文件夹,在里面创建Option.jsx,抽离Xcontent.jsx的content部分写入Option.jsx

Xcontent.jsx
import React, { Component } from 'react';
import {Layout, Menu, Icon,
} from 'antd';import Option from './SubNav/Option.jsx'const { SubMenu } = Menu;
const { Sider } = Layout;class Xcontent extends Component {state = {collapsed: false,option: 1};toggle = () => {this.setState({collapsed: !this.state.collapsed,});}toOption(option){this.setState({option});}render() {return (<Layout><Sider width={200} style={{ background: '#fff' }}><Menumode="inline"defaultSelectedKeys={['1']}defaultOpenKeys={['sub1']}style={{ height: '100%', borderRight: 0 }}><SubMenu key="sub1" title={<span><Icon type="user" />subnav 1</span>}><Menu.Item onClick={this.toOption.bind(this,1)} key="1">option1</Menu.Item><Menu.Item onClick={this.toOption.bind(this,2)} key="2">option2</Menu.Item><Menu.Item onClick={this.toOption.bind(this,3)} key="3">option3</Menu.Item><Menu.Item onClick={this.toOption.bind(this,4)} key="4">option4</Menu.Item></SubMenu><SubMenu key="sub2" title={<span><Icon type="laptop" />subnav 2</span>}><Menu.Item key="5">option5</Menu.Item><Menu.Item key="6">option6</Menu.Item><Menu.Item key="7">option7</Menu.Item><Menu.Item key="8">option8</Menu.Item></SubMenu><SubMenu key="sub3" title={<span><Icon type="notification" />subnav 3</span>}><Menu.Item key="9">option9</Menu.Item><Menu.Item key="10">option10</Menu.Item><Menu.Item key="11">option11</Menu.Item><Menu.Item key="12">option12</Menu.Item></SubMenu></Menu></Sider>{(()=>{let sendcontent = '';// 根据state中的option值传递显示内容switch(this.state.option){case 1:sendcontent = 'オラオラ'break;case 2:sendcontent = '無駄無駄'break;case 3:sendcontent = 'やれやれだぜ'break;case 4:sendcontent = 'だが断る'break;}return <Option content={sendcontent}/>})()}</Layout>);}
}export default Xcontent
Option.jsx
import React, { Component } from 'react';
import {Layout, Breadcrumb
} from 'antd';const { Content } = Layout;class Option extends Component {constructor(props){super(props)this.props = props}state = {collapsed: false,};toggle = () => {this.setState({collapsed: !this.state.collapsed,});}render() {return (<Layout><Layout style={{ padding: '0 24px 24px' }}><Breadcrumb style={{ margin: '16px 0' }}><Breadcrumb.Item>Home</Breadcrumb.Item><Breadcrumb.Item>List</Breadcrumb.Item><Breadcrumb.Item>App</Breadcrumb.Item></Breadcrumb><Content style={{background: '#fff', padding: 24, margin: 0, minHeight: 280,}}>//接收显示传进的值{this.props.content}</Content></Layout></Layout>);}
}export default Option

至此npm start,实现效果
Xcontent.jsx进行改造

Xcontent.jsx
import React, { Component } from 'react';
import {Layout, Menu, Icon,
} from 'antd';import Option from './SubNav/Option.jsx'const { SubMenu } = Menu;
const { Sider } = Layout;class Xcontent extends Component {state = {collapsed: false,option: 1,// 侧边菜单栏数据subMenus: [{title: 'sub1',childMenus: [{title: 'option1'},{title: 'option2'},{title: 'option3'},{title: 'option4'}]}]};toggle = () => {this.setState({collapsed: !this.state.collapsed,});}toOption(option){this.setState({option});}render() {return (<Layout><Sider width={200} style={{ background: '#fff' }}><Menumode="inline"defaultSelectedKeys={['1']}defaultOpenKeys={['sub1']}style={{ height: '100%', borderRight: 0 }}>{// 遍历数据方式生成结构this.state.subMenus.map((item,idx)=>{return (<SubMenu key={item.title} title={<span><Icon type="user" />{item.title}</span>}>{item.childMenus.map((item2,idx2)=>{return <Menu.Item onClick={this.toOption.bind(this,idx2+1)} key={idx2+1}>{item2.title}</Menu.Item>})}</SubMenu>)})}</Menu></Sider>{(()=>{let sendcontent = '';switch(this.state.option){case 1:sendcontent = 'オラオラ'break;case 2:sendcontent = '無駄無駄'break;case 3:sendcontent = 'やれやれだぜ'break;case 4:sendcontent = 'だが断る'break;}return <Option content={sendcontent}/>})()}</Layout>);}
}export default Xcontent

React_cli路由相关推荐

  1. RabbitMQ 入门系列(2)— 生产者、消费者、信道、代理、队列、交换器、路由键、绑定、交换器

    本系列是「RabbitMQ实战:高效部署分布式消息队列」和 「RabbitMQ实战指南」书籍的读书笔记. RabbitMQ 中重要概念 1. 生产者 生产者(producer)创建消息,然后发送到代理 ...

  2. 前端Vue学习之路(二)-Vue-router路由

    Vue学习之路 (二) Vue-router(基础版) 一.增加静态路由 二.动态路由+路由嵌套+404页面 三. 编程式导航 四.命名路由 五.命名视图 六.重定向和起别名 1.重定向 2.起别名 ...

  3. 发送快递:配置静态路由

    背景 基础组网,比如现在要实现相互通信,通过两台计算机来检测是否互通,但是它们中间通过一些路由器相互连接,这个时候,你要考虑,怎么配置这些路由器,包括给pc配地址,给路由器配地址,怎么定义这些网段! ...

  4. SpringCloud Alibaba微服务实战(七) - 路由网关(Gateway)全局过滤

    说在前面 全局过滤器作用于所有的路由,不需要单独配置,我们可以用它来实现很多统一化处理的业务需求,比如权限认证,IP 访问限制,监控,限流等等. 创建路由网关(Gateway)启动服务cloud-ac ...

  5. SpringCloud Alibaba微服务实战(六) - 路由网关(Gateway)

    什么是 Spring Cloud Gateway? Spring Cloud Gateway 是 Spring 官方基于 Spring 5.0,Spring Boot 2.0 和 Project Re ...

  6. 【微服务架构】SpringCloud之路由网关(zuul)

    什么是zuul zuul 是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用. Zuul 在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架.Zu ...

  7. flutter中的路由跳转

    在前面的基本路由和命名路由中,都演示了如何进行路由跳转,并且在路由跳转以后,可以借用系统自带的按钮就行返回上一级,当然了,也可以自定义按钮返回上一级. 返回上一级 在前面的例子中,当从Home.dar ...

  8. 路由vue-router进阶

    目录 1. 导航守卫 1.1. 全局守卫 1.2. 全局解析守卫 1.3. 全局后置钩子 1.4. 路由独享的守卫 1.5. 组件内的守卫 1.6. 完整的导航解析流程 2. 路由元信息 3. 获取数 ...

  9. VueJs开发笔记—IDE选择和优化、框架特性、数据调用、路由选项及使用

    一.IDE的选择: VsCode和WebStorm都是不错的选择,说一下两者的优缺点,调试便捷性来说两者不相上下. WebStorm缺点:性能方面VsCode远好于WebStorm: WebStorm ...

最新文章

  1. 国内IDC行业现状及投资策略分析
  2. 我的2015学习总结及2016的技术规划(2016.02)
  3. codeforces315Div1 B Symmetric and Transitive
  4. 进程间通信————信号
  5. 文献读的越多,离原创越远
  6. (数据库系统概论|王珊)第十章数据库恢复技术-第三节:故障种类
  7. node.js 学习笔记四:读取文件
  8. 【机器人】人类反应与机器的浑然一体—营救机器人诞生
  9. linux 环境下git的安装与配置
  10. 把excel每一行中的数据输出为一个txt文档的VBA函数
  11. 第二次小组实践作业小组每日进度汇报:2017-11-29
  12. 10个不太为人所知的,但实用的PHP函数(转)
  13. 生成26个大小写字母和0-9的六位随机验证码(python3.X)
  14. 福利工具,如何利用小程序免费下载积分文件呢?【第02期】
  15. 差分进化算法(python实现
  16. 计算机是如何计算 log 函数的?
  17. [DirectShow] 033 - Using Windowed Mode
  18. 手机和工业计算机运算能力对比,手机cpu和电脑cpu差距有多大_手机cpu跟电脑cpu差多少...
  19. HTML基础知识概要面试必备
  20. 【操作系统】一起了解操作系统咯 | 原码,反码,补码,你理解到位了吗?

热门文章

  1. C++ 中ASCII码转16进制数
  2. Vue - 图像加载时渐隐淡入效果(img)
  3. 2022-2028全球隔音涂料行业调研及趋势分析报告
  4. 二分查找算法 python实现
  5. CAD软件版本过低无法打开CAD图纸
  6. 在焦虑中积极应对压力
  7. pubg2019年7月服务器维护时间,绝地求生7月10日更新公告 绝地求生2019年7月10日更新内容...
  8. 苹果手机如何微信多开分身 苹果微信双开教程
  9. php渲染的时候如何提高用户体验,beforeSend怎么提高用户体验
  10. 微信小程序跳转公众号推文