亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

為什么要從 Vue 轉(zhuǎn)到 React,這篇文章為什么我們放棄了 Vue?不過對于大多數(shù)人來說,用 Vue 還是 React 不是自己說了算,多學一門技術(shù)不是壞處,而且 React 被大廠大量使用,要進入大廠也是必備的技能,筆者原先使用 Vue,由于 React 相關(guān)概念更加簡單,只要會 js 就行,轉(zhuǎn)到 React 只花了幾天時間(已經(jīng)回不去了~)。本文寫給想從 Vue 轉(zhuǎn)到 React 的同學,假設(shè)讀者有一定的 Vue 基礎(chǔ)。

JSX

先介紹 React 唯一的一個語法糖:JSX。

<div class='box' id='content'>
  <div class='title'>Hello</div>
  <button>Click</button>
</div>

上面的 DOM 結(jié)構(gòu)可以看出,要每個標簽只有 3 個信息:標簽名、屬性、子元素,所以上面等同于下面的 JSON 結(jié)構(gòu):

{
  tag: 'div',
  attrs: { className: 'box', id: 'content'},
  children: [
    {
      tag: 'div',
      arrts: { className: 'title' },
      children: ['Hello']
    },
    {
      tag: 'button',
      attrs: null,
      children: ['Click']
    }
  ]
}

當你寫下這個 React 組件是:

import React from 'react';

function MyComponent(props) {
    return <div>{props.hello}</div>
}

最終會被自動工具翻譯成:

import React from 'react';

function MyComponent(props) {
    return React.createElement('div', null, props.hello);
}

理解 JSX 語法并不困難,簡單記住一句話,遇到 {} 符號內(nèi)部解析為 JS 代碼,遇到成對的 <> 符號內(nèi)部解析為 html 代碼。React 就是通過這個小小語法糖,實現(xiàn)在 JS 里面寫 HTML,可能有小伙伴會說 HTML 與 JS 分離不是更好嗎?責職分明,混合只會更亂。但當你體驗到代碼自動提示,自動檢查,以及調(diào)試時精確定位到一行代碼的好處時,就清楚 React 和 Vue 的差距了。

語法糖轉(zhuǎn)換

習慣 Vue 的同學都知道很多語法糖,比如 v-if、v-for、v-bind、v-on 等,相比 Vue,React 只有一個語法糖,那就是 jsx/tsx。v-if 這些功能在 React 上都是通過原生 JAVAscript 實現(xiàn)的,慢慢你會發(fā)現(xiàn),其實你學的不是 React,而是 Javascipt,React 賦予你通過 js 完整控制組件的能力,這部分明顯比 Vue 的語法糖更加靈活,糖太多容易引來蟲子(Bug)。

 

v-if 條件渲染

vue 中寫法是這樣:

<template>
  <div>
    <h1 v-if="awesome1">Vue is awesome!</h1>
    <h1 v-else>else</h1>
    <h1 v-if="awesome2">Oh no</h1>
  </div>
</template>

<script>
module.exports = {
  data: function() {
    return {
      awesome1: true,
      awesome2: false,
    }
  }
}
</script>

在 React 函數(shù)組件中只需這樣:

import React, { useState } from 'react';

function Index() {
  const [awesome1, setAwesome1] = useState(true);
  const [awesome2, setAwesome2] = useState(false);

  return (
    <div>
      {awesome1 ? <h1>React is awesome!</h1> : <h1>Oh no</h1>}
      {awesome2 && <h1>React is awesome!</h1>}
    </div>
  );
}

export default Index;

只需使用 js 三目運算符語法即可完成條件渲染的功能。或者使用 && 邏輯,記住下面一句話就能過理解了:

遇到 {} 符號內(nèi)部解析為 JS 代碼,遇到成對的 <> 符號內(nèi)部解析為 HTML 代碼

v-for 列表渲染

Vue 中寫法:

<template>
  <ul id="array-rendering">
    <li v-for="item in items">
      {{ item.message }}
    </li>
  </ul>
</template>

<script>
module.exports = {
  data() {
    return {
      items: [{ message: 'Foo' }, { message: 'Bar' }]
    }
  }
}
</script>

React 寫法:

import React, { useState } from 'react';

function Index() {
  const [items, setItems] = useState([{ message: 'Foo' }, { message: 'Bar' }]);

  return (
    <ul id="array-rendering">
      {items.map((item, id) => <li key={id}>{item.message}</li>)}
    </ul>
  );
}

export default Index;

React 通過 js 的數(shù)組語法 map,將數(shù)據(jù)對象映射為 DOM 對象。只需學會 js,無需記住各種指令,如果要做列表過濾,直接使用 items.filter(...).map(...) 鏈式調(diào)用即可,語法上更加靈活,如果為了提高渲染性能,使用 useMemo 進行優(yōu)化即可,類似 Vue 的 computed。

v-model

Vue 中 v-model 是一個數(shù)據(jù)綁定語法糖,本質(zhì)上還是單向數(shù)據(jù)流,下面的子組件通過 update:title 同步 title 參數(shù)。

App.component('my-component', {
  props: {
    title: String
  },
  emits: ['update:title'],
  template: `
    <input
      type="text"
      :value="title"
      @input="$emit('update:title', $event.target.value)">
  `
})

React 寫法較為簡單,不需要像 Vue 一樣填鴨代碼,記住各種規(guī)則,所有數(shù)據(jù)和事件通過 props 傳遞就行了:

import React from 'react';

interface Props {
  title: string;
  onUpdateTitle: (title: string) => void;
}

function MyComponent(props: Props) {
  return <input
    type='text'
    value={props.title}
    onInput={e => props.onUpdateTitle(e.target.value)}
  />
}

更加容易整合 typescript 實現(xiàn)類型推斷,需要的邏輯都由 JS 完成,無需記住各種指令、使用方法,參數(shù)命名規(guī)則。

事件處理

Vue 中寫法

<template>
  <div id="inline-handler">
    <button @click="say('hi')">Say hi</button>
    <button @click="say('what')">Say what</button>
  </div>
</template>

<script>
module.exports = {
  methods: {
    say(message) {
      alert(message)
    }
  }
}
</script>

React 寫法:

import React, { useState } from 'react';

function Index() {
  const onClick = (message) => () => alert(message);

  return (
    <div id="inline-handler">
      <button onClick={onClick('hi')}>Say hi</button>
      <button onClick={onClick('what')}>Say what</button>
    </div>
  );
}

export default Index;

這里用了函數(shù)柯里化,一般事件處理這樣就行了:

import React from 'react';

function Index() {
  const onClick = () => alert('hi');

  return (
    <div id="inline-handler">
      <button onClick={onClick}>Say hi</button>
    </div>
  );
}

export default Index;

如果需要優(yōu)化緩存事件處理函數(shù),使用 useCallback 即可。可以看到 Vue 中的事件觸發(fā) this.$emit('click') 或者父組件中的代碼 v-on="say('hi')" 都使用了字符串的寫法,這樣非常不利于類型推斷,不利于代碼重構(gòu)。React 的函數(shù)寫法或者 class 寫法都直接使用 js 語法,沒有額外的東西,相比 Vue 更容易通過 IDE 進行重構(gòu)優(yōu)化。React 中無論方法還是變量,都是采用駝峰命名法,也可以自由定制,Vue 中必須混合小寫中隔線、駝峰、字符串組合,不利于統(tǒng)一代碼規(guī)范。

插槽

Vue 中寫法:

<template>
  <button class="btn-primary">
    <slot></slot>
  </button>
</template>

<script>
module.exports = {
  methods: {}
}
</script>

React 寫法:

import React from 'react';

function Index() {
  return (
    <button classNames="btn-primary">
      {props.children}
    </button>
  );
}

export default Index;

React 的插槽寫法沒有 Vue 那么復(fù)雜,也沒有“備用內(nèi)容”、“具名插槽”、“渲染作用域”、“作用域插槽”、“動態(tài)插槽名”,這些概念和特殊情況的處理,一切通過 JS 邏輯搞定就行了,怎么方便怎么來,比如備用內(nèi)容的實現(xiàn):

import React from 'react';

function Index() {
  // 默認情況下使用 Summit 作為按鈕文字
  return (
    <button classNames="btn-primary">
      {props.children === null ? 'Summit' : props.children}
    </button>
  );
}

export default Index;

樣式 & 屬性

這部分 Vue 的寫法實在是太麻煩了。。。每次我都要查查文檔具體怎么用,對象語法、數(shù)組語法、內(nèi)聯(lián)樣式,要記住的有點多,Vue 動態(tài)修改樣式的寫法:

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

<script>
module.exports = {
  data() {
    return {
      isActive: true,
      hasError: false
    }
  }
}
</script>

React 寫法:

import React, { useState } from 'react';

function Index() {
  const [isActive, setIsActive] = useState(true);
  const [hasError, setHasError] = useState(false);

  return (
    <div
      classNames={`static ${isActive ? 'active':'} ${hasError? 'text-danger':''}`}
    ></div>
  );
}

export default Index;

React 里面直接采用 JS 的模板字符串語法,如果樣式太多,可以使用 classnames 這個 npm 包,優(yōu)雅傳遞各種狀態(tài),使用非常簡單:

classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'

狀態(tài)管理

Vue 的狀態(tài)管理官方推薦使用 Vuex 也可采用 Redux。

Vue 轉(zhuǎn) React 指南,看這篇文章就夠了

 

引用官方文檔一段話:

如果你是來自 React 的開發(fā)者,可能會對 Vuex 和 Redux 間的差異表示關(guān)注,Redux 是 React 生態(tài)環(huán)境中最流行的 Flux 實現(xiàn)。Redux 事實上無法感知視圖層,所以它能夠輕松地通過一些簡單綁定和 Vue 一起使用。Vuex 區(qū)別在于它是一個專門為 Vue 應(yīng)用所設(shè)計。這使得它能夠更好地和 Vue 進行整合,同時提供簡潔的 API 和更好的開發(fā)體驗。

這段話其實暴露了 Vuex 的一個缺陷,它和 Vue 強綁定,無法獨立存在,這種一些項目升級和遷移時會有很大的麻煩。Redux 作為 React 的狀態(tài)管理方案之一其實不依賴于 React。

React 周邊的狀態(tài)管理方案特別多,如 Redux、Mobx、Recoil 等,各有各的亮點,其中使用最多的應(yīng)該是 Redux。

Vue 轉(zhuǎn) React 指南,看這篇文章就夠了

 

Redux 周邊生態(tài)也很豐富,可以更加下圖選擇不同的方案:

Vue 轉(zhuǎn) React 指南,看這篇文章就夠了

 

  • redux-thunk
  • redux-promise
  • redux-saga
  • redux-observable

由于這部分代碼較多,不詳細寫,不過如果你熟悉 Vuex 的概念,轉(zhuǎn)到 Redux 應(yīng)該不難。Vuex + axIOS 的做法和 Redux + redux-thunk 的寫法類似,不過現(xiàn)在 redux-saga 的方案被更多復(fù)雜項目采用,其中很重要的原因是 saga 的概念編寫異步代碼非常優(yōu)雅,且能夠很好地解決靜態(tài)問題(如果采用 Vuex + axios 的寫法會異常復(fù)雜、冗長),高度定制。

如果你要遷移 Vue 到 React,建議采用的方案是 Redux + saga,saga 的概念不是那么容易懂,學習需要一些時間,但當你學會的時候就會明白這種寫法比直接用 Promise 好太多了。

生命周期

Vue 的生命周期這里不再重復(fù),查詢官方文檔即可,React 生命周期如圖:

Vue 轉(zhuǎn) React 指南,看這篇文章就夠了

 

圖片可以在這里找到。一般情況下 class 寫法主要用到 componentDidMount 和 componentWillUnmount 鉤子,React 的函數(shù)寫法下可以用 useEffect 的執(zhí)行函數(shù)和清理函數(shù)去模擬 mount 和 unmount 過程:

import React, { useRef, useEffect } from 'react';

function Index() {
  const ref = useRef(null);
  
  useEffect(() => {
    console.log('mounted');

    return () => {
      console.log('will unmount');
    };
  }, []);

  return <input ref={ref}/>
}

export default Index;

useEffect 的原理這里不多說,可以看看相關(guān)文章:輕松學會 React 鉤子:以 useEffect() 為例。其實從 React hook 中可以看到,React 在慢慢淡化生命周期的概念,減少自己對用戶代碼的侵入,將更多控制權(quán)交給用戶。

原生 DOM 操作

這部分 Vue 和 React 都是采用 ref 寫法,Vue:

<template>
  <input ref="input" />
</template>

<script>
module.exports = {
  methods: {
    focusInput() {
      this.$refs.input.focus()
    }
  },
  mounted() {
    this.focusInput()
  }
}
</script>

React 寫法:

import React, { useRef, useEffect } from 'react';

function Index() {
  const ref = useRef(null);
  
  useEffect(() => {
    ref.current?.focuse();
  }, []);

  return <input ref={ref}/>
}

export default Index;

useEffect 是 React hook,在依賴數(shù)組為空的時候效果類似 componentDidMount 的生命周期函數(shù)(類似 Vue 的 mounted)。此外 useRef 不止用在這里,也可以掛載一些其他的東東,實現(xiàn)一些復(fù)雜操作,比如 previousValue 和對象屬性等。

分享到:
標簽:React
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定