react学习第四天笔记之简历项目

项目架构

  • 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

  • 下载模块
    • 命令:npm i --save antd
    • 蚂蚁设计网站:Ant Design
  • 在main.js中引入css文件;
    • 代码:import "antd/dist/antd.css"
  • 使用menu导航菜单和Icon图标
    • 引入模块,解构赋值:import {Menu,Icon} from "antd"
    • 分析:
      • <Menu>..</Menu>标签为外围容器
      • <Menu.Item>..</Menu.Item>标签为内部结构,需要设置key,为唯一值;
      • defaultSelectedKeys={["home"]}:指的是默认选中key设置为home的元素;
      • mode="inline":指的是内联列表
      • theme="dark":指的是主题为dark;
    • 注意:在设置默认的key时,必须设置与当前地址相同的那一项,如果赋值为定值,则页面刷新后,会默认再指向默认值对应的那项,可以通过父级的this.props.location.pathname来获取地址,然后自定义属性传给子级MenuList,再设置在defaultSelectedKeys中;
    • 问题:页面刷新后,menu会默认点亮设置的defaultSelectedKeys对应的keys值,所以需要在页面刷新后,重新设置新的值;
    • 方法:设置state值,在钩子函数中获取pathname值,再更新state值,进而设置新的defaultSelectedKeys值;参考链接:React 中使用antd,刷新时被选中的menu初始化的问题
    • 代码:
     <Menu
         defaultSelectedKeys={["home"]}
         mode="inline"
         theme="dark"
     >
         <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>
     </Menu>
    

字体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
  • 代码:
    • App/index.js代码:
     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>
    
    • App/index.css代码:
     /*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"));
    

简书链接

代码

  • webpack.config.js代码
 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"
 };
  • package.json代码
 {
   "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"
   }
 }

  • main.js代码
 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"));
  • routes-index.js代码
 //路由设置
 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;
  • layouts-App-index.js代码
 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>
         )
     }
 }
  • layouts-Menu-index.js代码
 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,值为布尔值,可以通过布尔值的不同,来设置不同状态下的显示和隐藏;
  • 代码:
    • main.js代码:
     //引入模块
     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"));
    
    • routes代码:
     //路由设置
     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代码:
      • index.js:
       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;
      
      • index.css:
       #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代码:
      • index.js:
       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;
      
      • index.css:
       .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;
       }
      
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容