1. 程式人生 > 程式設計 >vue轉react入門指南

vue轉react入門指南

目錄
  • 設計
  • 元件通訊
  • 生命週期
  • 事件處理
  • class和style
    • class
    • style
  • 條件渲染
    • 列表渲染
      • 元件巢狀
        • 獲取DOM
          • 文件結構
            • 路由
              • 動態路由&路由傳參
            • 巢狀路由
              • 路由跳轉
                • 路由守衛(登入驗證,特殊路由處理)
                  • 狀態管理
                    • 使用

                  因為新公司使用react技術棧,包括Umi、Dva、Ant-design等一系列解決方案。稍微熟悉一下之後,瞭解到雖然有些不同,但是還是大相徑庭。以下我就以兩個火熱的框架react16&2(在積極學習vue3中)從設計、書寫方式、API、生命週期及熱門生態做一下簡單的對比:

                  設計

                  react vue 說明
                  定位 構建使用者介面的庫 漸進式框架 react側重於library,vue側重於framework
                  渲染 setState更新state的值來達到重新render檢視 響應式資料渲染,修改了響應式資料對應的檢視也進行渲染 react需要考慮何時setState,何時render;vue只需要考慮修改資料
                  編寫方式 jsx template react是函式式,all in js;vue區分tempalte、script、style,提供語法糖,使用vue-loader編譯

                  元件通訊

                  react:嚴格的單向資料流

                  • 向下 props
                  • 向上 props func
                  • 多級傳遞 context

                  遵循萬物皆可props,onChange/setState()

                  vue:單向資料流

                  • 向下 props down
                  • 向上 events up(訂閱釋出)
                  • 多級傳遞 $attrs、$listeners

                  還有各種獲取元件例項(VueComponent),如:$refs、$parent、$children;通過遞迴獲取上級或下級元件,如:findComponentUpward、findComponentsUpward;高階元件:provide/reject,dispatch/broadcast

                  react vue 說明
                  子元件資料傳遞 props props 都是宣告式
                  元件狀態機 state data 管理元件的狀態,react使用setState更改,vue直接賦值,新屬性使用$set;vue使用函式閉包特性,保證元件data的獨立性,react本就是函式

                  生命週期

                  http://www.cppcns.com
                  react vue 說明
                  資料的初始化 constructor created
                  掛載 componentDidMount mounted dom節點已經生成
                  更新 componentDidUpdate updated react:元件更新完畢後,react只會在第一次初始化成功會進入componentDidmount,之後每次重新渲染後都會進入這個生命週期,這裡可以拿到prevProps和prevState,即更新前的props和state。 vue:在資料更改導致的虛擬 DOM 重新渲染和更新完畢之後被呼叫
                  解除安裝 componentWillUnmount destroyed 銷燬事件

                  事件處理

                  react

                  • React 事件的命名採用小駝峰式(camelCase),而不是純小寫
                  • 使用 JSX 語法時你需要傳入一個函式作為事件處理函式,而不是一個字串
                  • 不能通過返回 false 的方式阻止預設行為。你必須顯式的使用 preventDefault
                  • 不能解除安裝非Element標籤上,否則會當成props傳下去
                  function Form() {
                    function handleSubmit(e) {
                      e.preventDefault();
                      console.log('You clicked submit.');
                    }
                    return (
                      <form onSubmit={handleSubmit}>
                        <button type="submit">Submit</button>
                      </form>
                    );
                  }
                  
                  

                  vue

                  用在普通元素上時,只能監聽原生 DOM 事件。用在自定義元素元件上時,也可以監聽子元件觸發的自定義事件

                  //原生事件
                  <form v-on:submit.prevent="onSubmit"></form>
                  //自定義事件
                  <my-component @my-event="handleThis(123,$event)"></my-component>

                  vue事件修飾符:

                  • .stop - 呼叫 event.stopPropagation()。
                  • .prevent - 呼叫 event.preventDefault()。
                  • .capture - 新增事件偵聽器時使用 capture 模式。
                  • .self - 只當事件是從偵聽器繫結的元素本身觸發時才觸發回撥。
                  • .native - 監聽元件根元素的原生事件。
                  • .once - 只觸發一次回撥。
                  • .left - (2.2.0) 只當點選滑鼠左鍵時觸發。
                  • .right - (2.2.0) 只當點選滑鼠右鍵時觸發。
                  • .middle - (2.2.0) 只當點選滑鼠中鍵時觸發。
                  • .passive - (2.3.0) 以 { passive: true } 模式新增偵聽器

                  class和style

                  class

                  react

                  render() {
                    let className = 'menu';
                    if (this.props.isActive) {
                      className += ' menu-active';
                    }
                    return <span className={className}>Menu</span>
                  }

                  vue

                  <div
                    class="static"
                    :class="{ active: isActive,'text-danger': hasError }"
                  ></div>
                  
                   
                  <div :class="[{ active: isActive },errorClass]"></div>

                  style

                  react

                  <div style={{color: 'red',fontWeight: 'bold'}} />
                  
                  

                  vue

                  <div :style="[baseStyles,overridingStyles]"></div>

                  元件樣式的時候你可以在style標籤上宣告一個scoped來作為元件樣式隔離標註,如:<style lang="sass" scoped></style>。最後打包時其實樣式都加入一個hash的唯一值,避免元件間汙染

                  條件渲染

                  • react:jsx表示式, &&或者三元表示式;return false表示不渲染
                  • vue:表示式返回true被渲染,可巢狀多個v-else-if,v-else

                  列表渲染

                  rhttp://www.cppcns.comeact:使用.map,一個元素的 key 最好是這個元素在列表中擁有的一個獨一無二的字串

                  <ul>
                    {props.posts.map((post) =>
                      <li key={post.id}>
                        {post.title}
                      </li>
                    )}
                  </ul>
                  

                  vue:為了給 Vue 一個提示,以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素,你需要為每項提供一個唯一 key attribute

                  <li v-for="item in items" :key="item.message">
                    {{ item.message }}
                  </li>
                  

                  元件巢狀

                  react

                  預設插槽

                  <div className={'FancyBorder FancyBorder-' + props.color}>
                    {props.children}
                  </div>

                  具名插槽

                  <div className="SplitPane">
                    <div className="SplitPane-left">
                      {props.left}
                    </div>
                    <div className="SplitPane-right">
                      {props.right}
                    </div>
                  </div>www.cppcns.com
                  
                  <SplitPane left={<Contacts />} right={<Chat />} />
                  
                  

                  vue

                  預設插槽

                  <main>
                    <slot></slot>
                  </main>

                  具名插槽

                  <header>
                    <slot name="header"></slot>
                  </header>

                  獲取DOM

                  react:管理焦點,文字選擇或媒體播放。觸發強制動畫。整合第三方 DOM 庫

                  class MyComponent extends React.Component {
                    constructor(props) {
                      super(props);
                      this.myRef = React.createRef();
                    }
                    render() {
                      return <div ref={this.myRef} />;
                    }
                  }

                  vue:被用來給元素或子元件註冊引用資訊

                  <div ref="div">hello</div>
                  
                  this.$refs.p.offsetHeight
                  

                  文件結構

                  Umi

                  ├── config                   # umi 配置,包含路由,構建等配置
                  │   ├── config.ts            # 專案配置.umirc.ts優先順序更高,使用此方式需要刪除.umirc.ts
                  │   ├── routes.ts            # 路由配置
                  │   ├── defaultSettings.ts   # 系統配置
                  │   └── proxy.ts             # 代理配置
                  ├── mock                     # 此目錄下所有 js 和 ts 檔案會被解析為 mock 檔案
                  ├── public                   # 此目錄下所有檔案會被copy 到輸出路徑,配置了hash也不會加
                  ├── src
                  │   ├── assets               # 本地靜態資源
                  │   ├── components           # 業務通用元件
                  │   ├── e2e                  # 整合測試用例
                  │   ├── layouts              # 約定式路由時的全域性佈局檔案
                  │   ├── models               # 全域性 dva model
                  │   ├── pages                # 所有路由元件存放在這裡
                  │   │   └── document.ejs     # 約定如果這個檔案存在,會作為預設模板
                  │   ├── services  www.cppcns.com           # 後臺介面服務
                  │   ├── utils                # 工具庫
                  │   ├── locales              # 國際化資源
                  │   ├── global.less          # 全域性樣式
                  │   ├── global.ts            # 全域性 JS
                  │   └── app.ts               # 執行時配置檔案,比如修改路由、修改 render 方法等
                  ├── README.md
                  └── package.json
                  

                  vue_cli

                  ├── mock                       # 專案mock 模擬資料
                  ├── public                     # 靜態資源
                  │   └── index.html             # html模板
                  ├── src                        # 原始碼
                  │   ├── api                    # 所有請求
                  │   ├── assets                 # 主題 字型等靜態資源
                  │   ├── components             # 全域性公用元件
                  │   ├── directive              # 全域性指令
                  │   ├── filters                # 全域性 filter
                  │   ├── layout                 # 全域性 layout
                  │   ├── router                 # 路由
                  │   ├── store                  # 全域性 store管理
                  │   ├── utils                  # 全域性公用方法
                  │   ├── views                  # views 所有頁面
                  │   ├── App.vue                # 入口頁面
                  │   └── main.js                # 入口檔案 載入元件 初始化等
                  ├── tests                      # 測試
                  ├── vue.config.js              # vue-cli 配置如代理,壓縮圖片
                  └── package.json               # package.json
                  

                  路由

                  動態路由&路由傳參

                  react-router

                  • history.push(/list?id=${iwww.cppcns.comd})
                  • history.push({pathname: '/list',query: {id}})
                  • history.push(/list/id=${id})
                  • history.push({pathname: '/list',params: {id}})

                  獲取 props.match.query / props.match.params

                  vue-router

                  • this.$router.push({path: '/list',query: {id}})
                  • this.$router.push({path: '/list',params: {id}})

                  獲取 this.$router.query / this.$router.params

                  巢狀路由

                  -react

                  {
                    path: '/',component: '@/layouts/index',routes: [
                      { path: '/list',component: 'list' },{ path: '/admin',component: 'admin' },],}
                  
                  <div style={{ padding: 20 }}>{ props.children }</div>

                  使用props.children渲染子路由

                  vue-router

                  {
                    path: '/user/:id',component: User,children: [
                      {
                        path: 'profile',component: UserProfile
                      },{
                        path: 'posts',component: UserPosts
                      }
                    ]
                  }
                  
                  <div id="app">
                    <router-view></router-view>
                  </div>

                  使用vue原生元件/<router-view/>元件渲染子路由

                  路由跳轉

                  umi

                  <NavLink exact to="/profile" activeClassName="selected">Profile</NavLink>
                  history.push(`/list?id=${id}`)

                  vue

                  <router-link to="/about">About</router-link>
                  this.$router.push({path: '/list',query: {id}})

                  路由守衛(登入驗證,特殊路由處理)

                  • Umi
                  • vue-router

                  全域性路由守衛

                  全域性前置守衛:router.beforeEach

                   const router = new VueRouter({ ... })
                   router.beforeEach((to,from,next) => {
                     // ...
                   })
                  
                  

                  全域性後置守衛:router.beforeEach

                   router.afterEach((to,from) => {
                     // ...
                   })
                  
                  

                  狀態管理

                  多個檢視依賴於同一狀態或來自不同檢視的行為需要變更同一狀態;才需要使用狀態管理機。

                  dva vuex 說明
                  模組 namespace modules 解決應用的所有狀態會集中到一個比較大的物件,store物件可能變得相當臃腫
                  單一狀態樹 state state 唯一資料來源
                  提交狀態機 reducer mutations 用於處理同步操作,唯一可以修改 state 的地方
                  處理非同步操作 effects action 呼叫提交狀態機更改狀態樹

                  使用

                  dva: model connect UI

                  // new model:models/products.js
                  export default {
                    namespace: 'products',state: [],reducers: {
                      'delete'(state,{ payload: id }) {
                        return state.filter(item => item.id !== id);
                      },},};
                  //connect model
                  export default connect(({ products }) => ({
                    products,}))(Products);
                  
                  //dispatch model reduce
                  dispatch model reduce({
                    type: 'products/delete',payload: id,})
                  
                  

                  如有非同步操作,如ajax請求,dispath model effects,然後effects呼叫model reduce
                  vuex

                  // new module
                  const store = new Vuex.Store({
                    state: {
                      count: 1
                    },mutations: {
                      increment (state) {
                        state.count++
                      }
                    },actions: {
                      increment (context) {
                        context.commit('increment')
                      }
                    }
                  })
                  //bind UI
                  <input v-model="$store.state[modelesName].name"/>
                  //commit module mutation 
                  store.commit('increment')

                  如有非同步操作,如ajax請求,dispath module actions,然後actions呼叫module mutations

                  store.dispatch({
                    type: 'incrementAsync',amount: 10
                  })
                  

                  到此這篇關於vue轉react入門指南的文章就介紹到這了,更多相關vue轉react內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!