项目架构
- src文件夹:开发时的源代码
- assets:静态资源文件夹;
- fonts:引入的icon字体图标文件;
- css,js等静态资源文件
- containers:容器型组件
- About
- Contact
- Home
- Project
- Skill
- layouts:布局
- APP:总布局
- index.js:总布局文件,用于设置页面的总布局结构;
- index.css:用于设置自己的css样式;
- Menu:导航栏布局
- index.js:导航栏制作的布局,需要引入到APP中;
- index.css:自己的css样式;
- routes:路由
- index.js:路由设置的文件,用于各种路由设置,插入到main.js中,然后插入到页面;
- index.html:前端页面;
- main.js:入口文件,插入页面中的文件,用于引入各种资源,js模块,css文件;
- main-index.css:main.js中引入的css文件,用于替换引入的模块中的css样式,注意:必须设置在最下面;才能替换覆盖样式;
蚂蚁设计模块antd
字体Icon的引入
- 下载字体icon
- 引入步骤:
- 将fonts文件夹放在assets文件夹下;
- 在main.js主体文件下,引入iconfont.css文件;
- 通过class名来引入icon图标;类名可以参考demo_fontclass.html文件;
- 配置webpack.config.js中的module;(需要下载url-loader,file-loader模块)
module:{
rules:[
{//配置字体;
test:/\.(eot|svg|ttf|woff)(\?\w*)?$/,
use:"url-loader?limit=50000"
},
{//配置图片
test:/\.(png|git|jpg|jepg)$/,
use:"url-loader?limit=50000"
}
]
}
让模块有css3的运动效果
- 需要的插件:react-addons-css-transition-group
- 注意事项:
- 下载插件,并且引入插件;
- 让谁动,就把插件包裹在谁的外面;注意不要影响页面的大结构
- 配置好react-addons-css-transition-group
- 添加定位:ReactCSSTransitionGroup设置相对定位,需要运动的元素设置绝对定位;
- 设置css:把example改成我们设置的名字;同时写入动画;
- js文件中,要运动的标签名上必须有key,key是唯一的,即使只有一个元素动,也要设置key,key必须设置;
- 设置key时,可以设置this.props.location.pathname值;
- ReactCSSTransitionGroup设置参数分析:
-
className="appCompo"
:设置class类名,用于设置自己的样式;需要设置相对定位;
-
component="div"
:设置的<ReactCSSTransitionGroup>
标签在页面中默认显示为span标签,则通过此设置为div标签;
-
transitionName="appCom"
:用于设置css3过渡效果的css样式中,相对应的类名;
-
transitionEnterTimeout={500} transitionLeaveTimeout={200}>
:用于设置过渡元素的进入和离开的所需时间,与css设置相对应;
-
<div className="appCompoInner" key={this.props.location.pathname}> {this.props.children} </div>
:为运动的元素,添加绝对定位;必须设置唯一的key值,否则会出错;
- 链接文档:React 附件动画API ReactCSSTransitionGroup
- 代码:
import ReactCSSTransitionGroup from "react-addons-css-transition-group"
import "./index.css"
<div className={collapse?"appWrap-container appWrap-container-collapse":"appWrap-container"}>
<ReactCSSTransitionGroup
className="appCompo"
component="div"
transitionName="appCom"
transitionEnterTimeout={500}
transitionLeaveTimeout={200}>
<div className="appCompoInner" key={this.props.location.pathname}>
{this.props.children}
</div>
</ReactCSSTransitionGroup>
</div>
/*css3过渡效果代码*/
.appCompo{
position: relative;
height: 100%;
width: 100%;
}
.appCompo .appCompoInner{
position: absolute;
width: 100%;
}
.appCom-enter {
opacity: 0.01;
transform: translate3d(100%,0,0);
}
.appCom-enter.appCom-enter-active {
opacity: 1;
transform: translate3d(0,0,0);
transition: all 500ms ease-in;
}
.appCom-leave {
opacity: 1;
}
.appCom-leave.appCom-leave-active {
opacity: 0.01;
transition: all 200ms ease-in;
}
折叠菜单的效果
- 知识:
- 通过设置App自身的state状态,来控制元素不同类名的设置;
- 父级组件App设置state状态下的collapse属性,通过条件判断来控制元素不同类名的设置,进而显示不同的效果;
- 父级组件的collapse值,通过给子组件MenuList设置自定义属性,传给子组件MenuList
- 子组件通过this.props来获取父级传来的数据;
- 子组件传递数据给父组件:子组件中通过点击事件来控制父组件state状态下的collapse值的改变;
- 父组件设置函数changeCollapse,函数内设置state的状态;在MenuList标签上设置自定义属性将函数体传递给子组件,注意:保证函数体内的this为实例,此处使用的是箭头函数创建函数;也可以使用bind
- 子组件通过this.props获取到父组件传递的函数体,然后赋给点击事件;当点击事件触发时,执行函数,父组件state状态改变;
知识点
- 如果文件夹下,存在index.js文件,当通过import引入时,引入文件夹,即默认引入文件夹下的index.js文件;
-
import MenuList from "../Menu";
指的是引入文件夹Menu下的index.js文件;
- this.props.loaction.pathname可以获取路由地址;
- 创建route时,可以通过变量创建,导出时,导出变量名即可,引入到其他组件中使用时,不是标签,而是变量
const route=(
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="/about" component={About}/>
<Route path="/contact" component={Contact}/>
<Route path="/project" component={Project}/>
<Route path="/skill" component={Skill}/>
</Route>
</Router>
);
export default route;
- 引入到main.js中,插入index.html页面中代码:
import route from "./routes";//引入文件夹,就默认引入文件夹下的index.js文件;
render(route,document.getElementById("app"));
简书链接
代码
const webpack=require("webpack");
const path=require("path");
const HtmlWebpackPlugin=require("html-webpack-plugin");
const ExtractWebpackPlugin=require("extract-text-webpack-plugin");
module.exports={
entry:path.resolve(__dirname,"src/main.js"),
output:{
path:path.resolve(__dirname,"dist"),
filename:"my-third-bundle.js"
},
module:{
rules:[
{
test:/\.js(x)?$/,
use:"babel-loader",
exclude:/node_modules/
},
{
test:/\.css$/,
use:ExtractWebpackPlugin.extract({
fallback:"style-loader",
use:"css-loader"
})
},
{
test:/\.(eot|svg|ttf|woff)(\?\w*)?$/,
use:"url-loader?limit=50000"
},
{
test:/\.(png|git|jpg|jepg)$/,
use:"url-loader?limit=50000"
}
]
},
devServer: {
disableHostCheck: true, // 新增该配置项,防止浏览器控制台报错;
},
plugins:[
new ExtractWebpackPlugin({
filename:"style.css"
}),
new HtmlWebpackPlugin({
template:path.resolve(__dirname,"src/Index.html")
})
],
mode:"development"
};
{
"name": "day4",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --progress --colors --content-base dist --history-api-fallback",
"build": "webpack --progress --colors"
},
"keywords": [],
"author": "guomushan",
"license": "ISC",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"css-loader": "^2.1.0",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"html-webpack-plugin": "^3.2.0",
"prop-types": "^15.6.2",
"react-addons-css-transition-group": "^15.6.2",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"webpack": "^4.28.3",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.14"
},
"dependencies": {
"antd": "^3.11.6",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-router": "^3.0.5"
}
}
import React,{Component} from "react";
import ReactDom,{render} from "react-dom";
import route from "./routes";//引入文件夹,就默认引入文件夹下的index.js文件;
//引入蚂蚁设计的css样式;
import "antd/dist/antd.css"
//引入字体图标的css
import "./assets/fonts/iconfont.css";
//引入自己的css样式,用于覆盖其他样式
import "./main-index.css";
render(route,document.getElementById("app"));
//路由设置
import React,{Component} from "react";
import {Router,Route,browserHistory,IndexRoute} from "react-router";
import App from "../layouts/App";
import Home from "../containers/Home";
import About from "../containers/About";
import Contact from "../containers/Contact";
import Project from "../containers/Project";
import Skill from "../containers/Skill";
const route=(
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="/about" component={About}/>
<Route path="/contact" component={Contact}/>
<Route path="/project" component={Project}/>
<Route path="/skill" component={Skill}/>
</Route>
</Router>
);
export default route;
import React,{Component} from "react";
import {Link,IndexLink} from "react-router";
import ReactCSSTransitionGroup from "react-addons-css-transition-group"
import MenuList from "../Menu";
import "./index.css"
export default class App extends Component{
constructor(){
super();
this.state={
collapse:true
}
}
//箭头函数保证this指向;
changeCollapse=()=>{
this.setState({
collapse:!this.state.collapse
})
};
render(){
var {collapse}=this.state;//解构赋值
return(
<div className="appWrap">
<div className={collapse?"appWrap-menu appWrap-menu-collapse":"appWrap-menu"}>
<MenuList collapse={collapse} changeCollapse={this.changeCollapse}/>
</div>
<div className={collapse?"appWrap-container appWrap-container-collapse":"appWrap-container"}>
<ReactCSSTransitionGroup
className="appCompo"
component="div"
transitionName="appCom"
transitionEnterTimeout={500}
transitionLeaveTimeout={200}>
<div className="appCompoInner" key={this.props.location.pathname}>
{this.props.children}
</div>
</ReactCSSTransitionGroup>
</div>
</div>
)
}
}
import React,{Component} from "react";
import {Link} from "react-router";
import {Menu,Icon} from "antd"
import "./index.css"
export default class MenuList extends Component{
showMenuItem(data){
var {collapse}=this.props;
//遍历数据data,箭头函数匿名函数的模式 p=>(),其中p为形参;
return data.map(item=>(
<Menu.Item key={item.path}>
<Link to={item.path==="home"?"/":item.path}>
<i className={"iconn icon iconfont "+item.icon}/>
{collapse?"":<span className="msg">{item.msg}</span>}
</Link>
</Menu.Item>
))
}
render(){
var {collapse,changeCollapse}=this.props;
var data=[
{"path":"home","msg":"首页","icon":"icon-home"},
{"path":"about","msg":"关于我","icon":"icon-guanyuwomen"},
{"path":"project","msg":"技能知识","icon":"icon-zhuanyezhishijineng"},
{"path":"skill","msg":"项目经验","icon":"icon-xiangmu"},
{"path":"contact","msg":"联系我们","icon":"icon-lianxiwomen"}
];
return(
<div className="menu">
<p className={collapse?"menu-user menu-user-collapse":"menu-user"}><Icon type="codepen-circle"/><span>{collapse?"":"果木山"}</span></p>
<Menu
defaultSelectedKeys={["home"]}
mode="inline"
theme="dark"
>
{this.showMenuItem(data)}
</Menu>
<span className="jian" onClick={changeCollapse}><Icon type={collapse?"right":"left"}/></span>
</div>
)
}
}
简历项目实战复习
- 项目依赖
- antd:Layout布局 Menu导航菜单 Icon图标
- react-addons-css-transition-group:插件,给组件添加css3运动效果;
- react-router@3.x:固定版本,大于3.x的版本中History不能使用;
- 知识点:
- 使用Layout布局中的Menu组件时,要设置defaultSelectedKeys为变量,不能设置为定值,否则,页面刷新的时候,会默认加载设置的默认key值;
- 可以使用
this.props.location.pathname
来进行设置;
- css3运动效果中,包裹的运动元素上的key值,必须是变量,否则没有动画效果,也可以通过
this.props.location.pathname
来设置;
- 使用Layout布局中,会存在状态值collapsed,值为布尔值,可以通过布尔值的不同,来设置不同状态下的显示和隐藏;
- 代码:
//引入模块
import React from "react";
import ReactDom,{render} from "react-dom";
//引入antd的样式
import "antd/dist/antd.css";
//引入iconfont样式
import "./assets/icon/iconfont.css";
//引入自己的样式
import "./index.css";
//引入路由route
import routes from "./routes";
//渲染页面
render(routes,document.getElementById("app"));
//路由设置
import React,{Component} from "react";
import {Router,Route,browserHistory,IndexRoute} from "react-router";
import App from "../layouts/App";
import Home from "../containers/Home";
import Contact from "../containers/Contact";
import Project from "../containers/Project";
import Skill from "../containers/Skill";
import About from "../containers/About";
const route=(
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="/contact" component={Contact}/>
<Route path="/project" component={Project}/>
<Route path="/skill" component={Skill}/>
<Route path="/about" component={About}/>
</Route>
</Router>
);
export default route;
- App代码:
import React from "react";
//引入antd模块
import { Layout} from 'antd';
const { Content, Sider } = Layout;
//引入动画组件react-addons-css-transition-group
import ReactCSSTransitionGroup from "react-addons-css-transition-group";
//引入自定义模块
import MenuList from "../Menu";
import "./index.css"
class App extends React.Component{
state = {
collapsed: false,
pathname: "",
};
onCollapse = collapsed => {
this.setState({ collapsed });
};
UNSAFE_componentWillMount(){
this.setState({
pathname: this.props.location.pathname
})
}
render(){
return(
<Layout style={{ minHeight: '100vh'}}>
<Sider collapsible collapsed={this.state.collapsed} onCollapse={this.onCollapse} collapsedWidth={80}>
<div className="logo"/>
<MenuList collapsed={this.state.collapsed} pathname={this.state.pathname}/>
</Sider>
<Layout>
<Content style={{ margin: '16px',backgroundColor: 'lavenderblush'}}>
<ReactCSSTransitionGroup
className="appCompo"
component="div"
transitionName="appCom"
transitionEnterTimeout={500}
transitionLeaveTimeout={200}
>
<div className="appCompoInner" key={this.props.location.pathname}>
{this.props.children}
</div>
</ReactCSSTransitionGroup>
</Content>
</Layout>
</Layout>
)
}
}
export default App;
#app .logo {
height: 32px;
background: rgba(255, 255, 255, 0.2);
margin: 16px;
}
/*css3过渡效果代码*/
.appCompo{
position: relative;
height: 100%;
width: 100%;
}
.appCompo .appCompoInner{
position: absolute;
width: 100%;
height: 100%;
padding: 24px;
}
.appCom-enter {
opacity: 0.01;
transform: translate3d(80%,0,0);
}
.appCom-enter.appCom-enter-active {
opacity: 1;
transform: translate3d(0,0,0);
transition: all 500ms ease-in;
}
.appCom-leave {
opacity: 1;
}
.appCom-leave.appCom-leave-active {
opacity: 0.01;
transition: all 200ms ease-in;
}
- Menu代码:
import React,{Children} from "react";
import {Link} from "react-router";
//引入antd模块
import { Menu, Icon } from 'antd';
const { SubMenu } = Menu;
//引入样式
import "./index.css";
class Menus extends React.Component{
constructor(){
super();
this.state={
defaultSelectedKeys: ["home"]
}
}
UNSAFE_componentWillMount(){
//在钩子函数中获取数据;此处本地设置参数;实际开发中从服务器端获取数据
this.data=[
{"path":"home","msg":"首页","icon":"icon-my-home"},
{"path":"about","msg":"关于我","icon":"icon-dianhua"},
{"path":"project","msg":"技能知识","icon":"icon-gongrenjinengshujuku"},
{"path":"skill","msg":"项目经验","icon":"icon-gouwuche"},
{"path":"contact","msg":"联系我们","icon":"icon-dianhua"}
];
//设置menu的默认选中keys
var pathname=this.props.pathname;
if(pathname==="/"){
pathname="/home"
}
pathname=pathname.split("/")[1];
this.setState({
defaultSelectedKeys: [pathname]
})
}
render(){
//解构赋值
var {collapsed}=this.props;
//返回插入数据的标签
let MenuItem=this.data.map((item)=>{
return (
<Menu.Item key={item.path} style={{fontSize: "16px"}}>
<Link to={item.path==="home"?("/"):("/"+item.path)}>
<i className={"iconfont "+item.icon}></i>
<span style={{marginLeft: "10px"}}>{collapsed?"":item.msg}</span>
</Link>
</Menu.Item>
)
});
return (
<Menu theme="dark" defaultSelectedKeys={this.state.defaultSelectedKeys} mode="inline">
{MenuItem}
</Menu>
)
}
}
export default Menus;
.ant-menu-item .anticon, .ant-menu-submenu-title .anticon{
font-size: 16px;
}
.ant-menu-inline-collapsed > .ant-menu-item .anticon, .ant-menu-inline-collapsed > .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-item .anticon, .ant-menu-inline-collapsed > .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-submenu > .ant-menu-submenu-title .anticon, .ant-menu-inline-collapsed > .ant-menu-submenu > .ant-menu-submenu-title .anticon{
font-size: 16px;
}
网友评论