React筆記1

1.react基礎:類組件、函數式組件、ES5/ES6繼承

在建立一個vue項目的時候,

1.在index.js文件中引入react模塊,引入在須要的節點所須要的組件
import React from 'react'; // 必需要引入的模塊
import ReactDOM from 'react-dom'; // 給某一個DOM節點渲染時用到,它是從react中分離出來的

import App from '@/components/App'; // React的一個組件

// 將虛擬的組件渲染到視圖中
// 組件名字必須是大寫,若是是小寫的話它會認爲是html標籤,組件的文件名也建議大寫
ReactDom.render ( // render是一個鉤子函數
    <APP />,
    document.getElementById('root') //表示的是組件放到哪一個節點中
)

2.在components文件夾下,編寫組件App.jsx
import React from 'react'
/**
在react中開發組件模式:
 > ES6  class類寫法   類組件  
 > ES6  箭頭函數寫法   函數式組件   ----無狀態組件
*/
// return()   ()內部的代碼寫的是虛擬Dom,符合jsx語法
//class 類:
class App extends React.Component {
    render () {
        return (
        <div>hello react</div>
        )
    }
}
export default App;

// 函數式組件
const App = () => {
    return (
    <div> hello function</div>
    )
}


如何選擇類組件仍是函數式組件?
   若是一個組件須要有狀態,那麼必定不要寫函數式組件,函數式組件又會被成爲 無狀態組件,函數式組件通常會使用爲UI組件(只負責渲染視圖,數據都來源於父組件)---- 在react16.8的時候要注意一下(有另外一種說法)
  • ES5 的繼承,實質是先創造子類的實例對象this,而後再將父類的方法添加到this上面(Parent.apply(this))。
  • ES6 的繼承機制徹底不一樣,實質是先將父類實例對象的屬性和方法,加到this上面(因此必須先調用super方法),而後再用子類的構造函數修改this。

子類必須在constructor方法中調用super方法,不然新建實例時會報錯。這是由於子類本身的this對象,必須先經過父類的構造函數完成塑造,獲得與父類一樣的實例屬性和方法,而後再對其進行加工,加上子類本身的實例屬性和方法。若是不調用super方法,子類就得不到this對象。css

2.生命週期鉤子函數

React的生命週期的鉤子函數

掛載時 ---------- 初始化階段
  • constructor() -------聲明屬性
  • componentWillMount() --------即將掛載組件
  • render() --------初次渲染數據
  • componentDidMount() ----------組件掛載完畢,能夠在此處進行請求數據
更新時 ---------運行時階段
  • componenttWillReceiveProps(nextProps) --------將接收到組件的數據
  • shouldComponentUpdate() ------------- 當state或者props發生改變時,組件是否更新,默認更新,返回值爲布爾類型
  • componentWillUpdate() ------------組件即將更新
  • render() -------------組件更新
  • componentDidUpdate() ----------------組件更新完畢,dom操做
卸載時 ---------銷燬階段
  • componentWillUnmount() -------------組件銷燬---定時器、計數器等
錯誤處理
  • componentDidCatch() --------當react組件數出現錯誤時執行

經常使用的react的生命週期鉤子函數html

constructor() 經過給 this.state 賦值對象來初始化內部 state。爲事件處理函數綁定實例vue

render() 只要是組件就必須有的java

componentDidMount() 若是須要請求數據,若是須要DOM操做,實例化操做node

componentDidUpdate() 若是須要DOM操做,實例化操做react

componentWillUnmount() 若是須要清除定時器,計時器,實例對象webpack

3.什麼是JSX

jsx它既不是一個字符串也不是一個HTML,是javascript的語法拓展。jsx能夠生成react中的元素,組件就是由元素組成的。
jsx的特性屬性,在屬性中嵌入javascript代碼時,在大括號外面不用加引號
jsx能夠防止javascript腳本攻擊,由於在渲染的時候,它會先將代碼轉化成字符串。

4.props和state有什麼區別

props是隻讀的,它用在組件與組件之間
能夠把props理解爲從外部傳入組件內部的數據。因爲React是單向數據流,因此props基本上也就是從服父級組件向子組件傳遞的數據。
state可讀可寫,它用在組件內
它就是數據的狀態
  1. state是組件本身管理數據,控制本身的狀態,可變;
  2. props是外部傳入的數據參數,不可變;
  3. 沒有state的叫作無狀態組件,有state的叫作有狀態組件;
  4. 多用props,少用state。也就是多寫無狀態組件。

5.路由配置

項目目錄樹:入口找佈局,佈局找頁面,頁面找的是組件,組價中能夠找子組件ios

  1. 在入口文件中配置路由es6

    import { BrowserRouter as Router, Switch, Route } from react-router-dom
    import App from '@/layout/App'
    import Detail from '@/layout/Detail'
    
    <Router>
        <Switch>
         <Route path="/detail" component={ Detail } />
         <Route path="/" component={ App } />
     </Switch>
    </Router>
  2. 在佈局文件中配置路由:帶參數

    <Switch>
        <Route path="/detail/order" component={ Order }/>
        <Route path="/detail/:id" component={ Detail }/>
    </Switch>
  3. 在佈局文件中配置路由:不帶參數

    import Home from '@/view/Home'
    import Kind from '@/view/Kind'
    import Cart from '@/view/Cart'
    import User from '@/view/User'
    import { Route, Switch, NavLink, Redirect } from 'react-router-dom'
    
    <Switch>
          <Route path= '/home' component={ Home } />
          <Route path= '/kind' component={ Kind } />
          <Route path= '/cart' component={ Cart } />
          <Route path= '/user' component={ User } />
          <Redirect to ='/home' />   //重定向
    </Switch>
    
    <NavLink to="/home"><NavLink>  //點擊跳轉,若是有樣式變化用NavLink
     //<Link to={ "/detail/id=" + item.id }><Link>  //沒有樣式變化的跳轉,用Link

注:路由的查找是從上到下的,因此path = "/"必定要放在最下面,不然就直接進入path = "/"頁面,找不到path="/detail" 頁面

佈局文件不寫具體頁面,子組件數據由頁面傳遞,因此子組件中能夠用函數式組件

注:詳情頁跳轉時path="/detail/:id"

  1. 重定向和404頁面

    import NoMatch from '@/view/NoMatch';
    <Redirect exact from = '/' to ='/home' />  //exact表示只有「/」才能重定向到「/home」
       <Route component = { NoMatch } />

6.自定義封住組件

1.利用{...this.props}將父組件中的值傳遞到子組件中,在子組件中{ }使用

2.結合相似vue的插槽完成自定中介部分的內容

封裝Header組件

//<Header>組件
import React from 'react'

export default (props) => {
  console.log(props)
  const { left, right, content, onLeft, onRight } = props //從父組件中傳過來的值
  return (
    <ul>
      <li onClick = { () => {
        if(props.match.path === '/home') {
          return 
        }
        props.history.goBack()
        // onLeft()
      }
      }>
        {left}
      </li>
      <li>{props.children? props.children : content? content : ''}</li>
      <li onClick = { () => {
        onRight()
      }}>{right}</li>
    </ul>
  ) 
}
//父組件中引用子組件的地方
<Header
          left = "返回"
          content = "搜索"
          right = "掃一掃"
          onLeft = {() => {
            // this.props.history.goBack()
            console.log('返回')
          }}
          onRight = { () => {
            console.log('掃一掃')
          }}
          {...this.props}
          >
            <div className="seach">請輸入搜索的內容</div>
          </Header>
7.引入移動端react ant-design-mobile UI庫‘’
  1. 安裝 ant UI庫文件

    cnpm i antd-mobile -S
  2. 在index頁面中引入文件(引入 Promise 的 fallback 支持 (部分安卓手機不支持 Promise))

    將此段代碼直接替換
     <meta name="viewport" content="width=device-width, initial-scale=1" />
    替換爲:
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
      <script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script>
      <script>
        if ('addEventListener' in document) {
          document.addEventListener('DOMContentLoaded', function() {
            FastClick.attach(document.body);
          }, false);
        }
        if(!window.Promise) {
          document.writeln('<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js"'+'>'+'<'+'/'+'script>');
        }
      </script>
  3. 在config/webpack.config.js中添加UI庫的配置。(因爲咱們用到是react腳手架將config獨立出來了,沒有babel-plugin-文件)

    npm i babel-plugin-import -D
    在第357行,粘貼
    ["import", { libraryName: "antd-mobile", style: "css" }] // `style: true` 會加載 less 文件
  4. 基本配置完成,接下來須要哪一個組件引入便可

7.React 狀態管理器

1.Redux:(最基本的寫法)

ReduX並不獨屬於React,他是js的狀態管理容器,在vue中也能用,只是在react中用起來更好,react-redux是屬於react的

在store.js頁面中 -》 index.js頁面引入store監聽事件 -》在App頁面disptch觸發事件改變store中的值

//在store->index.js文件中配置狀態管理器
import { creatStore } from 'redux';

const reducer = (state = {
    bannerlist: [],
    prolist:[]
  },action) => {
    const { type, data } = action;
    switch (type) {
      case 'CHANGE_BANNER_LIST': return Object.assign({}, state, {bannerlist:data})
      case 'CHANGE_PRO_LIST': return Object.assign({}, state, { prolist: data })
      default:
        return state;
    }
  }

  const store = creatStore(reducer);

  export default store;
//在index.js入口文件中監聽狀態管理器的變化
import React from 'react'
import ReactDOM from 'react-dom'

import App from './App'
import store from './store'

function renderFn(){
  ReactDOM.render(
    <App />,
    document.getElementById('root')
  )
}

renderFn();

//  若是檢測到狀態管理器中有變化觸發
store.subscribe(renderFn)
//在須要使用狀態管理器數據的頁面中(App.jsx)請求數據,改變狀態狀態管理器中的數據
import React, { Component } from 'react';
import axios from 'axios';
import store from './store'

export default class extends Component {
  componentDidMount () {
    axios.get('https://www.daxunxun.com/banner').then(res => {
      console.log(res.data,'data');
      console.log(store,'store');
      store.dispatch({
        type: 'CHANGE_BANNER_LIST',
        data: res.data
      })
    })
    axios.get('https://www.daxunxun.com/douban').then(res => {
      store.dispatch({
        type: 'CHANGE_PRO_LIST',
        data: res.data
      })
    })
  }
  render () {
    console.log(store.getState(),'getState')
    const { bannerlist, prolist } = store.getState();
    return (
      <div>
        <h1>狀態管理器</h1>
        <ul>
          {
            prolist.map(item => (
              <li key = { item.id }>
                { item.title }
              </li>
            ))
          }
        </ul>
      </div>
    )
  }
}
2.redux + react-redux:(把一個組件拆分紅了 容器組件 和 UI組件)

容器組件只負責業務邏輯的處理,
UI組件只負責數據的渲染

將App.jsx文件拆分紅App.jsx和UI.jsx,前者負責寫業務邏輯,後者負責渲染數據

//在index.js入口文件中改成
ReactDOM.render(
  <Provider store = { store }>
    <App />
  </Provider>,
  document.getElementById('root')
)
//在App.jsx中寫業務 邏輯
import { connect } from 'react-redux'
import axios from 'axios';
import UI from './UI'

// ui組件須要的狀態
const mapStateToProps = (state) => {
  return {
    bannerlist: state.bannerlist,
    prolist: state.prolist
  }
}

// ui組件的業務邏輯
const mapDispatchToProps = (dispatch) => {
  return {
    getBannerlist () {
      axios.get('https://www.daxunxun.com/banner').then(res =>{
        dispatch({
          type: 'CHANGE_BANNER_LIST',
          data: res.data
        })
      })
    },
    getProlist () {
      axios.get('https://www.daxunxun.com/douban').then(res => {
        dispatch({
          type: 'CHANGE_BANNER_LIST',
          data: res.data
        })
      })
    }
  }
}

const App = connect(mapStateToProps, mapDispatchToProps)(UI)

export default App;
//在UI組件中渲染數據
import React, { Component } from 'react';

export default class extends Component {
  componentDidMount () {
    this.props.getBannerlist();
    this.props.getProlist();
  }
  render () {
    // console.log(store.getState(),'getState')
    const { bannerlist, prolist } = this.props;
    return (
      <div>
        <h1>狀態管理器</h1>
        <ul>
          {
            prolist.map(item => (
              <li key = { item.id }>
                { item.title }
              </li>
            ))
          }
        </ul>
      </div>
    )
  }
}
3.redux+ react-redux + react-thunk

將狀態管理器拆分到每一個頁面,而後在store->index文件中配置,單首創建一個action文件,將異步請求數據單拎出來。

// action頁面寫異步請求
import axios from 'axios';

export default {
  getBannerlist (dispatch) {
    axios.get('https://www.daxunxun.com/banner').then(res => {
      dispatch({
        type: 'CHANGE_BANNER_LIST',
        data: res.data
      })
    })
  }
 }
//狀態管理器的入口文件
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import home from './home'
import kind from './kind'

const reducer = combineReducers({
  home,
  kind
})
// applyMiddleware 函數的做用就是對 store.dispatch 方法進行加強和改造,使得在發出 Action 和執行 Reducer 之間添加其餘功能。
//引入thunk插件後,咱們能夠在actionCreators內部編寫邏輯,處理請求結果。而不僅是單純的返回一個action對象。
const store = createStore(reducer, applyMiddleware(thunk));

export default store;
//狀態管理器單個頁面
const reducer = (state = { 
  bannerlist: [],
  prolist: []
}, action) => {
  const { type, data } = action;
  switch (type) {
    case 'CHANGE_BANNER_LIST': 
      return Object.assign({}, state, {bannerlist: data});
    case 'CHANGE_PRO_LIST':
      return Object.assign({}, state, {prolist: data});
    default:
      return state;
  }
}

export default reducer;

8.利用腳手架建立一個React項目

1.安裝腳手架而且建立項目

cnpm / npm i create-react-app -g
create-react-app myapp

使用npx直接建立項目

npx是一種在npm中安裝工具,也能夠被單獨的下載使用
在npm 5.2.0 的時候發現會買一送一,自動安裝了npx。

npx create-react-app myapp
(npm 的版本必須在5.2.0以上)

2.修改配置文件、安裝依賴

運行 npm run eject 抽離配置文件

修改package.json ,配置dev指令

配置src文件夾的別名 @

cnpm i node-sass -D
cnpm i react-router-dom@4 redux react-redux redux-thunk axios antd-mobile -S

在src下面建立main.scss在首頁中引入

3.配置入口文件index.js

引入路由文件 import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';

引入狀態管理器文件 import store from './store';

配置文件 import { Provider } from 'react-redux';

全局引入組件庫css文件 import 'antd-mobile/dist/antd-mobile.css';

坑點:

1.console.log()打印了2次內容

若是在render中使用console.log,因爲react的生命週期中,在其初始化階段會執行一次render初次渲染,在運行時階段執行一次render渲染數據,因此會執行2次,也就打印了2次。

2.props提供的語法糖,能夠將父組件中的全部屬性複製給子組件。

{ ...this.props } 將父組件的路由信息傳給組件。 this.props主要包含:history屬性、location屬性、match屬性

3.爲啥寫重定向和404頁面在佈局文件中?

由於當咱們輸入網址的時候,它默認匹配「/」進入佈局頁面,若是你網址不對不算進入此項目,輸入正確的地址後即進入項目,默認「/」進入佈局頁面,進入佈局頁面咱們把它重定向到「/home」做爲首頁,若是輸入其餘匹配不到的就404頁面。其餘佈局頁面不用寫,由於咱們進入首頁後,其餘頁面都是經過頁面間跳轉的,不須要手動在網址上輸入。

相關文章
相關標籤/搜索