美文网首页
简书项目相关

简书项目相关

作者: 泡杯感冒灵 | 来源:发表于2022-03-30 18:15 被阅读0次
    react项目创建以及运行
    1. 先安装 npm install create-react-app --save
    2. 创建项目 npx create-react-app my-app
    3. cd my-app
    4. npm start
    组件里引入的css文件,其他组件是通用的,也就是说,不同组件引入的样式文件,有可能会产生冲突。这个时候需要我们引入第三方工具styled-components
    1. 安装 npm install styled-components --save
    2. 创建style.js文件,里边可以通过createGlobalStyle创建一些全局样式
    import { createGlobalStyle } from 'styled-components';
    // 比如reset.css可以写在这里 
    // 这里用的reset.css是 https://meyerweb.com/eric/tools/css/reset/
    export const GlobalStyle  = createGlobalStyle`
      html, body, div, span, applet, object, iframe,
      h1, h2, h3, h4, h5, h6, p, blockquote, pre,
      a, abbr, acronym, address, big, cite, code,
      del, dfn, em, img, ins, kbd, q, s, samp,
      small, strike, strong, sub, sup, tt, var,
      b, u, i, center,
      dl, dt, dd, ol, ul, li,
      fieldset, form, label, legend,
      table, caption, tbody, tfoot, thead, tr, th, td,
      article, aside, canvas, details, embed, 
      figure, figcaption, footer, header, hgroup, 
      menu, nav, output, ruby, section, summary,
      time, mark, audio, video {
        margin: 0;
        padding: 0;
        border: 0;
        font-size: 100%;
        font: inherit;
        vertical-align: baseline;
      }
      /* HTML5 display-role reset for older browsers */
      article, aside, details, figcaption, figure, 
      footer, header, hgroup, menu, nav, section {
        display: block;
      }
      body {
        line-height: 1;
      }
      ol, ul {
        list-style: none;
      }
      blockquote, q {
        quotes: none;
      }
      blockquote:before, blockquote:after,
      q:before, q:after {
        content: '';
        content: none;
      }
      table {
        border-collapse: collapse;
        border-spacing: 0;
      }
    `;
    
    • 然后在index.js里引入使用
    import {GlobalStyle} from './style.js';
    
    ReactDOM.render(
      <React.StrictMode>
        <GlobalStyle/>
        <App />
      </React.StrictMode>,
      document.getElementById('root')
    );
    
    用styled-components创建局部样式,需要用styled-components的组件 styled
    import styled from 'styled-components';
    
    // 这里的意思是,创建HeaderWrapper这样一个组件
    // HeaderWrapper本质是div这样一个标签,下边是标签的样式
    // 注意,需要把组件导出
    export const HeaderWrapper = styled.div`
        height:56px;
        background:red;
    `
    
    • 使用HeaderWrapper这个组件
    import React ,{Component} from 'react';
    import {HeaderWrapper} from './style';
    class Header extends Component {
        render(){
            return (
                <HeaderWrapper>header</HeaderWrapper>
            )
        }
    }
    
    export default Header;
    
    可以在src目录下,创建statics文件夹,用来存放静态资源,比如图片。
    • 存放的图片该怎么用呢?
    // 先引入
    import logoPic from '../../statics/logo.png';
    
    // style.js
    export const Logo = styled.a`
        position:absolute;
        top:0;
        left:0;
        display:block;
        width:100px;
        height:56px;
        background:url(${logoPic});
    `
    
    • 如果这个图片可以跳转,该怎么写跳转地址呢?
    // 方法1
    <HeaderWrapper>
          <Logo href='/'/>
    </HeaderWrapper>
    
    // 方法2 attrs方法,接收一个对象,对象里设置href
    export const Logo = styled.a.attrs({
        href:'/'
    })`
        position:absolute;
        top:0;
        left:0;
        display:block;
        width:100px;
        height:56px;
        background:url(${logoPic});
        background-size:contain;
    `
    
    iconfont引入项目
    • iconfont创建项目,找图标后,下载至本地


      image.png
    • 解压缩后,把iconfont命名的文件,复制到statics文件夹下,最好是statics里再创建一个文件夹,比如iconfont,然后把iconfont.css改为iconfont.js。


      image.png
    • 因为图标是通用的,所以,可以用createGlobalStyle创建为全局样式。特别需要注意,url后边的路径要改为./开头。
    import { createGlobalStyle } from 'styled-components';
    export const IconStyle  = createGlobalStyle`
      @font-face {
        font-family: "iconfont"; /* Project id 3282899 */
        src: 
            url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAQgAAsAAAAACDQAAAPRAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACDHAqDaINEATYCJAMQCwoABCAFhGcHPxtDBxEVnBHJfh7Y4DLlUlc4pBDD8IhG80ed0hKdLn2/g+fRjno/ycxmMwvwLFZgCaADvOiPrpbVqdLc/5y2bOypvqqg62TJswzeD/DPpeAGbtHzc3tVaigDcnJGbWJcvsSBVFoj0zuU3UpaAfr7PNfklaXItwOARSV1PR8e2NkK6EAXWYR7ez7nmW8Yu7iMcxDA0YwuqF59IhIAMYumN1QBMjBoVIGwXBbNL84FWNaKKSkXLIJfd6xBduGB2qx+gJ3u+6WWFmJB4Wm0RYbNCSwAlFR0KrvrjSHQn7ApCLC9AjxAA41mZpd55d4ZaD/RCI3L+46hDWCxKKigok2lbxhC+aq0VveBav3jiY9WGgVAK5jUUIFJQEFFGwIaKrvLT2AtA4AFIoCjHfgA5maxv0Iw0dndETY5mLjJ0pZ1fV9Vz02TjXmwdDeNaXTh2K4S9uzr+dBb396NXhw/v2nlm9z5NF1wiLJykWTtlZB4oDj4/Kgmt5yS19mW5LEW/5KYEuOuUcJjQrzFukUdu0xf2r7+FgvXx433gFg3JmqUWxiMn7DEQx1LS8m9QZfgxJW4LU+6m8Yee925OiVen7DxFpTlXXl8ss+ioSFgwhA5xgl/jmbx1NTRRrWeyeowZXCwMkx9hURIFIiihiv+ryfbZnE7ZucOZYgy2Fucksocjfpdh5WNyy9+i8IcgvV0Lb5/d8DLosymg/7+Gw9Wh0UMyQM9X/inSl8cU9ayXzOn/uClE1jRQ9K4cHGAD1O9ILg9taWktiql0tleYhendLB7jZ2SOX11il66wpjQnJvLukQlgXrMKPWyQP50Wdnw5tJUvO5NqpVJpdjJwcBubr9ZYxt+mMl/Moq/F+ewDICw7qG+QUij3gSgS/SrbkfDNXM/Wmyn3zY4zKov8+/nuoGQ6dSXviqZJH2xukk1SY0cBGPylKb8Z9F1j+SgAKc74E1mIIEvffgTIXQLlpVBKCLIhMZSwDCcBvAIaAEfS2c4GtJ7ckCikJQ+YiKBOjwBCHHcoIjhLjRxvDMMp4VHCn/wieMfjjESPV9AHbHmHA1CG8wreFYSM8NALt0NOkVo8KzoAXnuwTDIgpRMrzFG3sWA/OQoRAwYTyJY0c0wDBNIeeKjRYJLlM5EkeW9RLCSqDOHgxgQiA1gcgXwsEiIYTY5xT9vA+JQEGLAazIOCU6OB+kDMgJSDcZaG9eqOJNFck44KBAEA2BwkIoAVqwbCaVEApDmt/JBLAgBt0UsZYaok7G6WmF8fXR5mwCHdqQRJVqMePgr0eCWO16VxM7ViHvdjU4HAAAA') format('woff2'),
            url('./iconfont.woff?t=1648626401195') format('woff'),
            url('./iconfont.ttf?t=1648626401195') format('truetype'),
            url('./iconfont.svg?t=1648626401195#iconfont') format('svg');
      }
    
      .iconfont {
        font-family: "iconfont" !important;
        font-size: 16px;
        font-style: normal;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
      }
    `;
    
    • 然后,就可以通过各种方式展示了,比如Unicode 、Fontclass、Symbol
    <i className="iconfont">&#xe636;</i>
    
    经过拆分后,Header组件就变得非常明晰了。
    image.png
    • 首先style.js里放的是组件里所有的样式。
    import styled from 'styled-components';
    import logoPic from '../../statics/logo.png';
    
    // 这里的意思是,创建HeaderWrapper这样一个组件
    // HeaderWrapper本质是div这样一个标签,下边是标签的样式
    export const HeaderWrapper = styled.div`
        height:56px;
        border-bottom:1px solid #f0f0f0;
        position:relative;
    `
    
    export const Logo = styled.a.attrs({
        href:'/'
    })`
        position:absolute;
        top:0;
        left:0;
        display:block;
        width:100px;
        height:56px;
        background:url(${logoPic});
        background-size:contain;
    `
    export const Nav = styled.div`
       width:960px;
       height:100%;
       padding-right:50px;
       margin:0 auto;
       box-sizing:border-box;
    `
    
    export const NavItem = styled.div`
      line-height:56px;
      padding:0 15px;
      font-size:17px;
      color:#333;
      &.left{
          float:left;
      }
      &.right{
          float:right;
          color:#969696;
      }
      &.active{
          color:#ea6f5a;
      }
    `
    export const NavSearch = styled.input.attrs({
        placeholder:'搜索'
    })`
        width:160px;
        height:38px;
        padding:0 30px 0 20px;
        margin-top:9px;
        margin-left:20px;
        box-sizing:border-box;
        border:none;
        outline:none;
        border-radius:19px;
        background:#eee;
        font-size:14px;
        color:#666;
        &::placeholder{
            color:#999;
        }
        &.focused{
            width:240px;
        }
        &.slide-enter{
            transition:all .2s ease-out;
        }
        &.slide-enter-active{
            width:240px;
        }
        &.slide-exit{
            transition:all .2s ease-out;
        }
        &.slide-exit-active{
            width:160px;
        }
    `
    
    export const Addition = styled.div`
        position:absolute;
        right:0;
        top:0;
        height:56px;
    `
    
    export const Button = styled.div`
        float:right;
        line-height:38px;
        border-radius:19px;
        margin-right:20px;
        padding:0 20px;
        margin-top:9px;
        border:1px solid #ec6149;
        font-size:14px;
        &.reg{
            color:#ec6149;
        }
        &.writting{
            color:#fff;
            background:#ec6149;
        }
    `
    
    export const SearchWrapper = styled.div`
        position:relative;
        float:left;
        .iconfont{
            position:absolute;
            right:5px;
            bottom:5px;
            width:30px;
            line-height:30px;
            border-radius:15px;
            text-align:center;
            &.focused{
                background:#777;
                color:#fff;
            }
        }
        
    `
    
    • index.js是Header组件的整体的内容,里边包含了一个UI组件(负责渲染页面上的样式),和一个容器组件(负责处理页面上的数据和逻辑)。


      image.png
      image.png
    • 组件里要存放是内容(这里是focused),都是放在store下的reducer里
    import * as constants from './constants';
    
    const defaultState = {
        focused:false
    };
    
    export default (state = defaultState,action) => {
        if(action.type === constants.SEARCH_FOCUS){
            const newState = JSON.parse(JSON.stringify(state));
            newState.focused = true;
            return newState;
        }
        if(action.type === constants.SEARCH_BLUR){
            const newState = JSON.parse(JSON.stringify(state));
            newState.focused =false;
            return newState;
        }
        return state
    }
    
    • 所以,一个组件和它相关的页面展示的内容,包括数据的内容,都统一放在Header文件夹下,以后拆分和管理会更方便。出了什么BUG,定位问题也更便捷。
    利用create-react-app的特性,来创建模拟数据
    • 在public文件夹下创建一个api文件夹,里边先创建一个headerList.json

    • 我们通过http://localhost:3000/api/headerList.json可以访问到headerList.json里的内容。原理是利用create-react-app的特性。

      image.png
    • create-react-app的底层也是一个node的服务器,当我们去访问api下边的headerList.json的时候,它会先到工程目录下有没有对应的路由,如果找不到,它还会到public目录下去找这个路由,如果它发现public下有api这个目录,同时api这个目录下有headerList.json这个文件,它就会把api这个目录下headerList.json这个文件的内容输出出来。通过这个特性,我们可以在public这个目录下,写一些假的数据。

    • 常见的做法就是,后端接口开发出来之前,可以先在public目录下创建一个API目录,里边放一些假数据,然后上线之前,再把API这个文件夹删除掉,然后当上线或者跟后端联调的时候,因为API这个文件夹已经不存在了,请求的时候,就会以接口的内容为主了。

    注意,如果我们通过fromJS方法把一个JS对象转换为immutable对象后,那么这个immutable对象里的属性如果也是immutable对象,比如defaultState的list数组。当我们在改变list的时候,就要注意,不要用普通对象去赋值list了,同样要用immutable对象给它赋值。
    const defaultState = fromJS({
        focused:false,
        list:[]
    });
    
    
    • changelist 接收data后,创建一个action,这个action的data属性的值也是一个immutable对象
    
    const changelist = (data) => ({
        type:constants.CHNAGE_LIST,
        data:fromJS(data)
    })
    
    • dispatch把changelist创建的action,派发给store,store结合原来的数据和这个action传给reducer.
    export const getList = () => {
        return (dispatch) => {
            axios.get('/api/headerList.json').then((res)=>{
                const data = res.data;
                dispatch(changelist(data.data));
            }).catch(()=>{
                console.log('error')
            })
        }
    }
    
    • reducer里state通过set方法修改list的时候,action.data也是一个immutable对象
    export default (state = defaultState,action) => {
        if(action.type === constants.SEARCH_FOCUS){
            return state.set('focused',true);
        }
        if(action.type === constants.SEARCH_BLUR){
            return state.set('focused',false);
        }
        if(action.type === constants.CHNAGE_LIST){
            return state.set('list',action.data);
        }
        return state
    }
    
    如果我在组件上传一个url,然后想把这个url用到background的url里怎么办?这个时候需要借助styled-components的一个props语法
                // 组件上定义imgUrl并赋值
                <RecommendWrapper>
                   <RecommendItem imgUrl="https://test.png"/>
                </RecommendWrapper>
    
                // styled.js
                export const RecommendItem = styled.div`
                      width:280px;
                      height:50px;
                      background:url(${(props)=>props.imgUrl});
                      background-size:contain;
                `
                          
    

    相关文章

      网友评论

          本文标题:简书项目相关

          本文链接:https://www.haomeiwen.com/subject/vptujrtx.html