此时的css打包是自动添加到index的style标签里面
04.添加图片的依赖 创建/app/images/avatar.jpg 修改/app/component/Header.js import React from 'react'; import Avatar from '../images/avatar.jpg'; class Header extends React.Component { render() { return ( <div className="header"> <div className="header-con"> <div className="user"> <span className="text">欢迎您!</span> <span className="avatar"> <img src=http://www.likecs.com/{Avatar} alt="" /> </span> </div> </div> </div> ) } } export default Header; 添加图片依赖/webpack.config.js module: { rules: [ { test: /.*\.(gif|png|jpe?g|svg)$/, use: [{ loader: 'url-loader', options: { limit: 10000, name: 'images/[name].[ext]' } }, { loader: 'image-webpack-loader' }] }, ] }, 05.添加预编译语言-sass <!--less和sass都用,此处用sass--> npm install sass-loader node-sass --save-dev 修改webpack.config.js module: { rules:[{ test: /\.scss$/, use: [{ loader: 'style-loader' }, { loader: 'css-loader', options: { sourceMap: true } }, { loader: 'sass-loader', options: { sourceMap: true, outputStyle: 'expanded', sourceMapContents: true } }] },] }, 添加app.scss @import 'body'; @import 'header'; @import 'sidebar'; @import 'content'; 将app.css拆分成body.scss/header.scss/sidebar.scss/content.scss <!--例:header.scss--> .header { position: fixed; top: 0; left: 150px; right: 0; padding: 0 30px; height: 61px; background: #ebebeb; .user { position: absolute; right: 0; top: 15px; height: 30px; line-height: 30px; color: gray; } .header-con { position: relative; width: 100%; height: 60px; } .text { float: left; height: 30px; } .avatar { float: right; width: 30px; height: 30px; img { width: 100%; height: 100%; border-radius: 90%; } } } 修改/app/component/app.js import '../style/app.css'; <!--修改为--> import '../style/app.scss'; 重新打包 webpack 安装第二个预编译语言less npm install less less-loader --save-dev 修改webpack.config.js module: { rules: [ { test: /\.less$/, use: [{ loader: 'style-loader' }, { loader: 'css-loader', options: { sourceMap: true } }, { loader: 'less-loader', options: { sourceMap: true, outputStyle: 'expanded', sourceMapContents: true, } }] }, ] }, 06.添加一个ui框架antd-designantd-design
npm install antd --save <!--babel-plugin-import必须要装--> npm install babel-plugin-import --save-dev 引入antd样式 <!--在App.js中引入--> import 'antd/dist/antd.css' 或 import 'antd/dist/antd.less' <!--在app.scss中引入--> @import "~antd/dist/antd.css"; 使用组件,修改content.js import React from 'react'; import Table from 'antd/lib/Table'; class Content extends React.Component { render() { const columns = [{ title: '姓名', dataIndex: 'name', key: 'name', }, { title: '年龄', dataIndex: 'age', key: 'age', }, { title: '电话号码', dataIndex: 'number', key: 'number', }, { title: '邮箱', dataIndex: 'email', key: 'email', }]; const data = []; for (let i = 1; i < 15; i++) { let obj = { name: 'doudou', age: 32, number: 123456789, email: '123456789@163.com', }; obj.key = i; data.push(obj); } return ( <div className="content"> <Table columns={columns} dataSource={data}/> </div> ) } } export default Content; babel-plugin-import插件从 antd 引入模块即可,无需引入样式,babel-plugin-import 会加载 JS 和 CSS
修改.babelrc //.babelrc { "plugins": [ [ "import", { "libraryName": "antd", "style": true //引入less,如果使用css文件就改为'css' } ] ] } 修改/app/component/Content.js import {Table} from 'antd';此时app.scss和App.js中引入的antd.css可以去掉了
问题如果在编译antd的样式文件报错,更换一个less,当前是@2.7.2
使用antd-design 更改/app/component/App.js import React from 'react'; import Header from './layout/Header'; import Content from './layout/Content'; import Sidebar from './layout/Sidebar'; import '../style/app.scss'; import {Layout} from 'antd'; class App extends React.Component { constructor() { super(); this.state = { collapsed: false }; this.toggle = () => { this.setState({ collapsed: !this.state.collapsed }) }; } render() { return ( <Layout className="layout-app"> <Layout.Sider trigger={null} collapsible collapsed={this.state.collapsed} > <Sidebar/> </Layout.Sider> <Layout> <Layout.Header style={{background: '#fff', padding: 0}}> <Header collapsed={this.state.collapsed} toggle={this.toggle} /> </Layout.Header> <Layout.Content style={{margin: '24px 16px', padding: 24, background: '#fff', minHeight: 280}}> <Content/> </Layout.Content> </Layout> </Layout> ) } } export default App; 修改/app/component/layout/Header.js import React from 'react'; import avatar_img from '../../images/avatar.jpg'; import {Icon, Avatar} from 'antd'; class Header extends React.Component { constructor(props) { super(props); } render() { const { collapsed, toggle } = this.props; return ( <div className="layout-header"> <Icon className="trigger" type={collapsed ? 'menu-unfold' : 'menu-fold'} onClick={toggle} /> <Avatar className="avatar" src=http://www.likecs.com/{avatar_img}/> </div> ) } } export default Header; 修改/app/component/layout/Sidebar.js import React from 'react'; import {Menu, Icon} from 'antd'; class Sidebar extends React.Component { constructor(props) { super(props); } render() { return ( <div className="layout-sidebar"> <div className="logo"/> <Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}> <Menu.Item key="1"> <Icon type="user"/> <span>nav 1</span> </Menu.Item> <Menu.Item key="2"> <Icon type="video-camera"/> <span>nav 2</span> </Menu.Item> <Menu.Item key="3"> <Icon type="upload"/> <span>nav 3</span> </Menu.Item> </Menu> </div> ) } } export default Sidebar; 修改/app/component/layout/Content.js import React from 'react'; import {Table} from 'antd'; class Content extends React.Component { render() { const columns = [{ title: '姓名', dataIndex: 'name', key: 'name', }, { title: '年龄', dataIndex: 'age', key: 'age', }, { title: '电话号码', dataIndex: 'number', key: 'number', }, { title: '邮箱', dataIndex: 'email', key: 'email', }]; const data = []; for (let i = 1; i < 15; i++) { let obj = { name: 'doudou', age: 32, number: 123456789, email: '123456789@163.com', }; obj.key = i; data.push(obj); } return ( <Table columns={columns} dataSource={data}/> ) } } export default Content; 新建layout.scss .layout-app { height: 100%; } .layout-sidebar { .logo { height: 32px; background: #333; border-radius: 6px; margin: 16px; } } .layout-header { .trigger { font-size: 18px; line-height: 64px; padding: 0 16px; cursor: pointer; transition: color .3s; &:hover { color: #108ee9; } } .avatar { float: right; margin-top: 16px; margin-right: 16px; cursor: pointer; } } 07.引入路由react-router 安装react-router npm install react-router-dom --save 修改/app/app.js import './index.html'; import './styles/app.less'; import React from 'react'; import ReactDom from 'react-dom'; import App from './components/App.jsx'; import {BrowserRouter, Route} from 'react-router-dom'; ReactDom.render( <BrowserRouter> <Route path="http://www.likecs.com/" component={App}/> </BrowserRouter> , document.getElementById('root') ); 修改/app/component/App.js import React from 'react'; import Home from './Home'; import Login from './Login'; import {Route} from 'react-router-dom'; class App extends React.Component { componentDidMount() { const { location, history } = this.props; if (location.pathname === '/home' || location.pathname === 'http://www.likecs.com/') { history.replace('/home') } else if (location.pathname === '/login') { history.replace('/login') } } render() { return ( <div className="app"> <Route path="/home" component={Home}/> <Route path="/login" component={Login}/> </div> ) } } export default App; 添加/app/component/home/Home.js import React from 'react'; import {matchPath} from 'react-router-dom'; import Header from './Header'; import Content from './Content'; import Sidebar from './Sidebar'; import {Layout} from 'antd'; export default class Home extends React.Component { constructor(props) { super(props); this.state = { collapsed: false }; this.ress = ['content01', 'content02', 'content03']; this.res = null; const match = matchPath(this.props.history.location.pathname, { path: '/home/:res' }); if (match) { this.res = match.params.res; } this.toggle = () => { this.setState({ collapsed: !this.state.collapsed }) }; } componentWillMount() { if (!this.res || !this.res.length || this.ress.indexOf(this.res) === -1) { this.props.history.replace(`/home/content01`) } } render() { return ( <Layout className="layout-app"> <Layout.Sider trigger={null} collapsible collapsed={this.state.collapsed} > <Sidebar res= {this.res}/> </Layout.Sider> <Layout> <Layout.Header style={{background: '#fff', padding: 0}}> <Header collapsed={this.state.collapsed} toggle={this.toggle} /> </Layout.Header> <Layout.Content style={{margin: '24px 16px', padding: 24, background: '#fff', minHeight: 280}}> <Content/> </Layout.Content> </Layout> </Layout> ) } } 添加/app/component/login/Login.js import React from 'react'; import {Form, Icon, Input, Button, Checkbox} from 'antd'; const FormItem = Form.Item; class Logining extends React.Component { constructor(props) { super(props); this.handleSubmit = (e) => { const { history } = this.props; e.preventDefault(); this.props.form.validateFields((err, values) => { if (!err) { if (values.userName === 'admin' && values.password === '123456') { history.replace('/home') } console.log('Received values of form: ', values); } }); } } render() { const { getFieldDecorator } = this.props.form; return ( <div className="login"> <Form onSubmit={this.handleSubmit} className="login-form"> <FormItem> {getFieldDecorator('userName', { rules: [{required: true, message: 'Please input your username!'}], })( <Input prefix={<Icon type="user" style={{fontSize: 13}}/>} placeholder="Username"/> )} </FormItem> <FormItem> {getFieldDecorator('password', { rules: [{required: true, message: 'Please input your Password!'}], })( <Input prefix={<Icon type="lock" style={{fontSize: 13}}/>} type="password" placeholder="Password"/> )} </FormItem> <FormItem> {getFieldDecorator('remember', { valuePropName: 'checked', initialValue: true, })( <Checkbox>Remember me</Checkbox> )} <a className="login-form-forgot" href="">Forgot password</a> <Button type="primary" htmlType="submit" className="login-form-button"> Log in </Button> Or <a href="">register now!</a> </FormItem> </Form> </div> ); } } const Login = Form.create()(Logining); export default Login; 修改/app/component/layout/Sidebar.js import React from 'react'; import {Menu, Icon} from 'antd'; import {NavLink} from 'react-router-dom'; export default class Sidebar extends React.Component { render() { const { res } = this.props; return ( <div className="layout-sidebar"> <div className="logo"/> <Menu theme="dark" mode="inline" defaultSelectedKeys={[res]} > <Menu.Item key="content01"> <NavLink to="/home/content01"> <Icon type="user"/> <span>nav 1</span> </NavLink> </Menu.Item> <Menu.Item key="content02"> <NavLink to="/home/content02"> <Icon type="video-camera"/> <span>nav 2</span> </NavLink> </Menu.Item> <Menu.Item key="content03"> <NavLink to="/home/content03"> <Icon type="upload"/> <span>nav 3</span> </NavLink> </Menu.Item> </Menu> </div> ) } } 修改/app/component/layout/Content.js import React from 'react'; import {Route} from 'react-router-dom'; import Content01 from './content01'; import Content02 from './content02'; import Content03 from './content03'; export default class Content extends React.Component { render() { return ( <div> <Route path="/home/Content01" component={Content01}/> <Route path="/home/Content02" component={Content02}/> <Route path="/home/Content03" component={Content03}/> </div> ) } } 修改/app/index.html <!DOCTYPE html> <html lang="en"> <head> <base href="http://www.likecs.com/"> <meta charset="UTF-8"> <title>hello world</title> </head> <body> <div></div> <script src="http://www.likecs.com/app.js"></script> </body> </html> 08.引入状态管理react-redux阮一峰redux