Vue3 和 Vue2 的異同及開發中具體區別

来源:https://www.cnblogs.com/flytree/archive/2022/08/24/16618379.html
-Advertisement-
Play Games

總體來說 性能提升 重寫了虛擬DOM的實現(跳過靜態節點,只處理動態節點) update性能提高1.3~2倍 服務端渲染速度提高了2~3倍 樹搖(Tree shaking) 可以將無用模塊“剪輯”掉,僅打包需要的 原理: ES6 Module引入進行靜態分析,故而編譯的時候正確判斷到底載入了那些模塊 ...


目錄

總體來說

性能提升

  1. 重寫了虛擬DOM的實現(跳過靜態節點,只處理動態節點)
  2. update性能提高1.3~2倍
  3. 服務端渲染速度提高了2~3倍

樹搖(Tree shaking)

可以將無用模塊“剪輯”掉,僅打包需要的
原理:

  1. ES6 Module引入進行靜態分析,故而編譯的時候正確判斷到底載入了那些模塊
  2. 靜態分析程式流,判斷那些模塊和變數未被使用或者引用,進而刪除對應代碼

參考:介紹一下 tree shaking 及其工作原理

碎片化節點(Fragment)

在 vue2.x 中,每個組件只能有一個根,所以,寫每個組件模板時都要套一個父元素。
在 vue3 中,為了更方便的書寫組件模板,新增了一個類似 dom 的標簽元素 ,也就是 vue3 中組件可以擁有多個根了。
這樣做的好處在於:減少標簽層級, 減小記憶體占用。

傳送門 (Teleport)

可以將一個組件內部的一部分模板“傳送”到該組件的 DOM 結構外層的位置去。

Suspense

用於協調對組件樹中嵌套的非同步依賴的處理。
如果在渲染時遇到非同步依賴項 (非同步組件和具有 async setup() 的組件),它將等到所有非同步依賴項解析完成時再顯示預設插槽。
https://cn.vuejs.org/api/built-in-components.html#suspense

更好的TypeScript支持

Composition API

組合式API,替換原有的 Options API
根據邏輯相關性組織代碼,提高可讀性和可維護性
更好的重用邏輯代碼(避免mixins混入時命名衝突的問題)
相容了VUE2中的寫法,原有Options API依然可以延用

響應式原理

不再基於 Object.defineProperty而是基於ES6中的Proxy

開發時差異

image

0. setup

組合式API以setup函數作為組件的入口

<script setup> 是在單文件組件 (SFC) 中使用組合式 API 的編譯時語法糖。當同時使用 SFC 與組合式 API 時該語法是預設推薦。相比於普通的 <script> 語法,它具有更多優勢:

  • 更少的樣板內容,更簡潔的代碼。
  • 能夠使用純 TypeScript 聲明 props 和自定義事件。
  • 更好的運行時性能 (其模板會被編譯成同一作用域內的渲染函數,避免了渲染上下文代理對象)。
  • 更好的 IDE 類型推導性能 (減少了語言伺服器從代碼中抽取類型的工作)。
// setup 函數的第一個參數是組件的 props 
// 沒有vue2.x中的this指向vue對象了
export default {
  props: {
    title: String
  },
  setup(props) {
    console.log(props.title)
  }
}

1. 生命周期調用

<script setup>
// 在vue中解構出方法
import { onMounted, onUpdated } from 'vue'

onMounted(() => {
  ...
})

onUpdated(() => {
  ...
})
</script>

beforeCreate -> 使用 setup()
created -> 使用 setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
errorCaptured -> onErrorCaptured

2. 響應式(數據)API

ref
接受一個參數值並返回一個響應式且可改變的 ref 對象

  1. ref 對象擁有一個指向內部值的單一屬性 .value
  2. 當ref在模板中使用的時候,它會自動解套,無需在模板內額外書寫 .value
import { ref } from "vue";
export default {
  setup() {
    let Num = ref(0),
        isShow = ref(false);

    return {
      Num,
      isShow
    };
  }
};

reactive

  1. 接收一個普通對象然後返回該普通對象的響應式代理等同於 2.x 的 Vue.observable()
  2. 響應式轉換是“深層的”:會影響對象內部所有嵌套的屬性

使用toRefs(state)可將其創建的傳為Refs類型,方便在模板中直接取值,而不用.value

import { ref, reactive } from "vue";
export default {
  props: { title: String },
  setup() {
    let state = reactive({
      Num: 0,
      arr: [1, 2]
    });
    let change = () => {
      state.arr[0] = state.arr[0] + 1;
      state.name = "flytree";
    };

    return {
      state,
      change
    };
  }
};

相關的一些方法:
unref / toRef / toRefs / isRef / isProxy / isReactive / isReadonly

3.計算屬性computed

傳入一個 getter 函數,返回一個預設不可手動修改的 ref 對象

const count = ref(1);
const plusOne = computed(() => count.value + 1);
console.log(plusOne.value); //2
plusOne.value++; //錯誤!

或者傳入一個擁有 get 和 set 函數的對象,創建一個可手動修改的計算狀態

const count = ref(1);
const plusOne = computed({
  get: () => count.value + 1,
  set: val => {
    count.value = val - 1;
  }
});
plusOne.value = 1;
console.log(count.value); //0

4.偵聽器watch

watchEffect
立即執行傳入的一個函數,並響應式追蹤其依賴,併在其依賴變更時重新運行該函數

export default {
  props: {
    title: String,
  },
  setup(props) {
    watchEffect(() => {
      console.log(`title is: ` + props.title);
    });
  }
};

watch

  1. watch API 完全等效於 2.x this.$watch
  2. watch 需要偵聽特定的數據源,併在回調函數中執行副作用
  3. 預設情況是懶執行的,也就是說僅在偵聽的源變更時才執行回調偵聽單個數據源
點擊查看代碼
// 偵聽器的數據源可以是一個擁有返回值的 getter 函數,也可以是 ref
const state = reactive({ count: 0 })
watch(
  () => state.count,
  (count, prevCount) => {
    /* ... */
  }
);

const count = ref(0)
watch(count, (count, prevCount) => {
  /* ... */
});
import { ref, reactive, toRefs, computed, watch } from "vue";
export default {
  setup() {
    ....

    let ratio = ref("--");
    watch(state, (state, preState) => {
      let total = state.supNum + state.oppNum;
      ratio.value =
        total === 0 ? "--" : ((state.supNum / total) * 100).toFixed(2) + "%";
    });

    return {
      ...,
      ratio
    };
  }
};

5. 獲取DOM元素refs

模板的Refs
當使用組合式 API 時,reactive refs 和 template refs 的概念已經是統一的

點擊查看代碼
<template>
  <div ref="root"></div>
</template>

<script>
  import { ref, onMounted } from 'vue';
  export default {
    setup() {
      const root = ref(null);
      onMounted(() => {
        console.log(root.value);
      });
      return {
        root
      };
    }
  }
</script>

6. 路由使用, VUEX ,VUE掛載

先要解構出方法,再去創建對應路由,store或vue對象,其它一樣

Vue Router 4.x


import { createRouter, createWebHashHistory } from 'vue-router';
import routes from './routes';

const router = createRouter({
    history: createWebHashHistory(),
    routes
});

router.beforeEach(async (to, from, next) => { ... })
export default router;

Vue Router 3.x

import VueRouter from 'vue-router'
import routes from './routes';

const router = new VueRouter({
  routes
})
export default router;

VUEX 4.x

import { createStore, createLogger } from 'vuex';
export default createStore({
  state: {},
  mutations: {},
  actions: {},
  plugins: [createLogger()]
})

VUEX 3.x

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {},
  state: {},
  mutations: {},
  actions: {},
})
export default store

實例創建

VUE 3.x

import { createApp } from 'vue';
const app = createApp(App);
app.use(store);
app.use(router);
app.mount('#app');

VUE 2.x

import Vue from 'vue'

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

7. 自定義指令處理技巧

export default function directive(app) {
    app.directive('xxx', {
        // 指令首次綁定到元素且在安裝父組件之前...「等同於bind」
        beforeMount(el, binding, vnode, prevVnode) {
            // binding:數據對象
            //   + arg:傳給指令的參數   v-xxx:n -> arg:"n"
            //   + modifiers:修飾符對象 v-xxx.stop -> modifiers:{stop:true}
            //   + value:指令綁定的值   v-xxx="1+1" -> value:2
            //   + oldValue:之前綁定的值
        },
        // 安裝綁定元素的父組件時...「等同於inserted」
        mounted() {},
        // 在包含組件的VNode更新之前...
        beforeUpdate() {},
        // 在包含組件的VNode及其子VNode更新後...「等同於componentUpdated」
        updated() {},
        // 在卸載綁定元素的父組件之前...
        beforeUnmount() {},
        // 指令與元素解除綁定且父組件已卸載時...「等同於unbind」
        unmounted() {}
    });
};
// main.js
import {
    createApp
} from 'vue';
import App from './App.vue';
import directive from './directive';
const app = createApp(App);
directive(app);
app.mount('#app');

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目錄 gun組織 項目 Linux版本 指令下達和執行 如何關機 linux Base gun組織 項目 copyleft:代表無版權。 copyright:代表有版權 opensource:開放源代碼、軟體誰都可以使用、誰都可以傳播、都可二次開發 free:免費 GPL:通用許可證協議,如果軟體打 ...
  • shell前言 什麼是shell shell-‘殼’ 命令解釋器,一種應用程式 shell語言特點 SHELL語言是指UNIX操作系統的命令語言,同時又是該命令語言的解釋程式的簡稱。 Shell本身是一個用C語言編寫的程式,它是用戶使用Unix/Linux的橋梁,用戶的大部分工作都是通過Shell完 ...
  • 操作系統的”進程”很早就出現了,許多教科書上定義這個概念總是晦澀難懂。電腦技術發展太快了,簡單的概念經過無數次演化,也會變得複雜。我們追溯一下操作系統的發展歷史,就能理解進程解決了什麼問題、為什麼這樣設計。進程是獨立功能的程式的一次動態執行過程,也是系統資源分配的獨立實體。每個進程都擁有獨立的地址... ...
  • 作者:Stephen Thorn 翻譯:劉玲玲 原文:https://www.percona.com/blog/2020/10/08/the-criticality-of-a-kubernetes-operator-for-databases/ 一些剛接觸 Kubernetes 的公司嘗試使用傳統環 ...
  • 資料庫如何在 Kubernetes 上運行?如果可以,哪些類型的資料庫和數據最適合使用 K8s?讓我們一起來看看。 Kubernetes 是用於自動部署、擴展和管理容器化應用程式的一個開源的容器編排解決方案。儘管 Kubernetes 最初是為無狀態應用程式設計的,但隨著有狀態工作負載的日益流行,K ...
  • 註:本文分析內容基於 MySQL 8.0 版本 文章開始前先複習一下官方文檔關於 DECIMAL 類型的一些介紹: The declaration syntax for a DECIMAL column is DECIMAL(M,D). The ranges of values for the ar ...
  • 眾所周知MySQL聯合索引遵循最左首碼匹配原則,在少數情況下也會不遵循(有興趣,可以翻一下上篇文章)。 創建聯合索引的時候,建議優先把區分度高的欄位放在第一列。 至於怎麼統計區分度,可以按照下麵這種方式。 ...
  • 我們又把近期的一些社區熱點問題做了一次彙總,同步給所有關註StoneDB的同學們~ 提問Qustions & 解答Answers Q:現在StoneDB單機什麼硬體規格部署能分析100TB級別的數據? A:像這麼大的存儲量,系統一般是分析類的,存儲可以是單塊盤容量是7.6TB的SSD,CPU核數和主 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...