React簡書開發實戰課程筆記——4

Jarns發表於2018-09-24
一、styled-components 擴充套件

React中, 一個檔案中引入css樣式表後,其他所有js檔案中都可以使用這個樣式表,也就是說css樣式表是全域性的,這樣可能會造成樣式衝突,所以藉助第三方模組:styled-components,可以讓css樣式表只對指定的元件起作用

  • 安裝:npm install styled-components --save
  • 使用:

這個擴充套件不是把樣式寫在css檔案中,而是寫在js檔案中(有點奇葩啊)。

新建一個js檔案用於寫樣式(後面就叫這個js檔案為樣式檔案)。

  • 由於有的css樣式還是需要公用的,比如reset.css樣式表,所以下面先介紹下怎麼公用樣式:

    import { injectGlobal } from 'styled-components';  //injectGlobal 是styled-components的一個API
    
    //將css程式碼寫在injectGlobal後面的反引號裡,就可以公用這些css程式碼
    injectGlobal`
      body {
        margin: 0;
        padding: 10px;
        font-family: sans-serif;
      }
    `
    
  • 其他需要對單個元件生效的css程式碼需要這樣寫:

    樣式檔案:

    const HeaderWrapper = styled.div`
      color: red;
    `;
    const Logo = styled.a`
      width: 100px;
    `;
    

    其實就是將html標籤和css樣式定義為一個元件,然後再使用這個元件。最終還是會被瀏覽器解析成真正的html標籤

    元件檔案:

    render () {
      return (
        <HeaderWrapper>
          <Logo></Logo>
        </HeaderWrapper>
      )
    }
    
  • 在這個裡面你可以使用scss的語法,比如:

    const Logo = styled.input`
      border: 1px solid #000;
      
      &.focused {
        border: 1px solid blue;
      }
      &:placeholder {
        color: #999;
      }
    `;
    
  • 如果要使用屬性,比如:a標籤的href屬性,有兩種寫法:

  1. const Logo = styled.a`
      color: #000;
    `;
    render () {
      return (
        <Logo href="#"></Logo>  //和正常的html標籤用法一樣
      )
    }
    
  2. const Logo = styled.a.attrs({  //將屬性寫成物件的形式
      href: '#',
    })`
      color: #000;
    `;
    
  • 如果要用css新增圖片,比如:background: url('./logo.png');,這種傳統的寫法就不行了。需要另一種寫法:

    import logoImg from './logo.png';  //需要先將圖片檔案引入
    
    const Logo = styled.a`
      width: 100px;
      background: url(${logoImg});
    `;
    

二、拆分reducer.js

如果只有一個reducer的話,隨著業務邏輯的增加,程式碼會變的愈來愈多,reducer會變得越來越大,所以最好將其拆分成不同的塊,每個塊對應一個reducer.js檔案。

比如: 網頁頭部的state拆分到headerReducer.js中。

下面是如何將所有的reducer檔案連線起來:

import { combineReducers } from 'redux';  //combineReducers是redux中的一個API,用於連線多個reducer
import headerReducer from './headerReducer.js';  //引入拆分出去的reducer
import footerReducer from './footerReducer.js';

const reducer =  combineReducers({
  header: headerReducer,
  footer: footerReducer 
});

export default reducer;

拆分之後再使用state中的資料就不能直接:this.state了,需要這樣寫:this.state.header.xxx,即需要指明: 是state下哪個塊的資料

三、immutable

用於將物件設定為不可更改
可用於保護state,state是不允許修改的,為了防止誤修改,可以藉助immutable庫

  • 安裝:npm install immutable

  • 使用:

    在用到state的檔案里加上這句話:

    import { fromJS } from 'immutable';
    

    然後:

    const defaultStore = fromJS({  //immutable中的fromJS方法將state資料保護起來
      value: ''
    });
    

    之後如果要使用或者更改注意:這裡說的更改並不是真正的修改state就要使用immutable提供的setget方法:

    this.state.set('value', 'hello');
    
    console.log(this.state.get('value'););
    
    //如果要同時更改多個state,有兩種方法:
    //1、
    this.state.set().set().set()...
    
    //2、
    this.state.merge({
      value: 'hello',
      list: ["hello", "world"]
    });
    

    這裡說明一下為什麼用immutable設定state為不可修改之後還能更改state。

    set的原理是這樣的: 根據以前的state傳入的資料,返回一個新的state。這樣修改state的目的實現了,但實際state並沒有修改。所以,使用immutable不僅保護了state,而且又可以愉快的修改了~


四、redux-immutable
  • 安裝:npm install redux-immutable

  • 使用:

    import { combineReducers } from 'redux';
    改為:
    import { combineReducers } from 'redux-immutable';
    
    //如果要get有子目錄的state,比如:state.header.value  //state下的header下的value
    //使用redux-immutable之後,就不能再向immutable那樣使用了(this.state.header.get('value'))
    //必須給header也要加上get方法:
    this.state.get('header').get('value');
    
    //可以簡寫成:
    this.state.getIn(['header', 'value']);  //注意書寫順序
    

五、react-router

作用就是根據不同的url,顯示不同的頁面資訊

  • 安裝:npm install react-router-dom
  • 使用:
import { BrowserRouter, Route } from 'react-router-dom';

<BrowserRouter>
  <div>  //BrowserRouter中只能有一個元素,所以包裹一個div
    <Route path='/' exact component={Home}></Route>
    <Route path='/detail' exact component={Detail}></Route>
  </div>
</BrowserRouter>

說一下其中的exact,作用是讓路徑完全匹配,否則,當訪問/detail目錄時,同時也會訪問到根目錄/


有錯誤或不足,歡迎評論指正~

待續…

相關文章