vue 3.x 如何高效學成?本文詳解

来源:https://www.cnblogs.com/chengxuyuanaa/archive/2020/06/08/13068777.html
-Advertisement-
Play Games

前言 本文所分享的是關於 vue 3.x 在用法上的改變,而不是在代碼實現上的不同。 雖然 vue2 到 vue3 的實現大改,但在用法上變化基本不大,比較明顯的一個變化就是添加了 setup(){} 函數了,幾乎所有的配置變成了以函數的方式進行定義。即使是這樣,但小改動還是很多的。本文主要分享的是 ...


前言

本文所分享的是關於 vue 3.x 在用法上的改變,而不是在代碼實現上的不同。

雖然 vue2 到 vue3 的實現大改,但在用法上變化基本不大,比較明顯的一個變化就是添加了 setup(){} 函數了,幾乎所有的配置變成了以函數的方式進行定義。即使是這樣,但小改動還是很多的。本文主要分享的是 vue 2.x 與 vue 3.x 之間一些常見用法的差異。雖然記錄的不多,但也不算少。本文資料來源:github.com/vuejs/rfcs/…

當然這裡預設你已經熟練掌握了 vue 2.x 的使用,下麵我們就來看看。

 

 

新增

composition-api

1.邏輯復用和代碼組織

這是 vue 3.0 的一個核心變更了。除了改了我們定義狀態的書寫方式外,也為我們提供體驗更棒的邏輯復用和代碼組織,新的方式可以讓你把同一個業務邏輯的代碼(狀態,計算屬性,方法等)都放到一塊。這聽起來可能有點不明不白,但如果你寫過比較複雜的組件,你就會發現,這個好。舊版本的 created、beforeCreated 鉤子函數已費棄,在 vue 3.0 中用 setup 代替。
另外註意:光理論是不夠的。在此贈送2020最新企業級 Vue3.0/Js/ES6/TS/React/node等實戰視頻教程,想學的可進裙 519293536 免費獲取,小白勿進哦!

2.更好的類型推斷

更好的支持 TypeScript。

可以看這篇文章:github.com/vuejs/rfcs/…

或者閱讀這篇(中文):vue-composition-api-rfc.netlify.app/zh/

完整的 API:vue-composition-api-rfc.netlify.app/zh/api.html

teleport 組件

teleport 組件它只是單純的把定義在其內部的內容轉移到目標元素中,在元素結構上不會產生多餘的元素,當然也不會影響到組件樹,它相當於透明的存在。為什麼要有這個組件?為了有更好的代碼組織體驗。比如:有時,組件模板的一部分在邏輯上屬於此組件,但從技術角度來看(如:樣式化需求),最好將模板的這一部分移動到 DOM 中的其他位置。

比如:一些 UI 組件庫的 模態窗、對話框、通知,下拉菜單等需要通過 z-index 來控制層級關係,如果都只是在不同的組件或者元素層級中,那麼 z-index 的層級順序就難以保證。可能你會說很多 UI 庫不是都已經是這樣的實現了的嗎?至於這個 UI 庫是如何實現的,我猜應該是直接操作 DOM。為什麼還要提供這個 teleport 組件呢?可能是因為vue 本身的使命使然:儘量不讓開發者直接操作 DOM,這些事都統一由 VUE 來完成。開發者可以把更多的時間放在業務的開發上。

<teleport to="#modals">
  <div>A</div>
</teleport>
<teleport to="#modals">
  <div>B</div>
</teleport>

<!-- result-->
<div id="modals">
  <div>A</div>
  <div>B</div>
</div>
複製代碼

更多細節可看:github.com/vuejs/rfcs/…

Suspense

載入非同步組件,在非同步組件載入完成成並完全渲染之前 suspense 會先顯示 #fallback 插槽的內容 。

<Suspense>
  <template>
    <Suspended-component />
  </template>
  <template #fallback>
    Loading...
  </template>
</Suspense>
複製代碼

#fallback 其實是插件 v-solt 的簡寫,而第一個 template 沒有給,則為預設插槽。

變更

插槽 slot 語法

github.com/vuejs/rfcs/…

適用版本:Version: 2.x,Version: 3.x

未來版本的 vue 中可以說合二為一了(slot 和 slot-scope)

<!-- vue 2.x -->
<foo>
  <bar slot="one" slot-scope="one">
    <div slot-scope="bar">
      {{ one }} {{ bar }}
    </div>
  </bar>

  <bar slot="two" slot-scope="two">
    <div slot-scope="bar">
      {{ two }} {{ bar }}
    </div>
  </bar>
</foo>

<!-- vue 3.x -->
<foo>
  <template v-slot:one="one">
    <bar v-slot="bar">
      <div>{{ one }} {{ bar }}</div>
    </bar>
  </template>

  <template v-slot:two="two">
    <bar v-slot="bar">
      <div>{{ two }} {{ bar }}</div>
    </bar>
  </template>
</foo>
複製代碼

我覺得這是好事,合二為一,不會讓人有一點點的困惑。

簡寫

<TestComponent>
  <template #one="{ name }">Hello {{ name }}</template>
</TestComponent>
複製代碼

指令動態參數

適用版本:Version: 2.x,Version: 3.x

<!-- v-bind with dynamic key -->
<div v-bind:[key]="value"></div>

<!-- v-bind shorthand with dynamic key -->
<div :[key]="value"></div>

<!-- v-on with dynamic event -->
<div v-on:[event]="handler"></div>

<!-- v-on shorthand with dynamic event -->
<div @[event]="handler"></div>

<!-- v-slot with dynamic name -->
<foo>
  <template v-slot:[name]>
    Hello
  </template>
</foo>

<!-- v-slot shorthand with dynamic name -->
<!-- pending #3 -->
<foo>
  <template #[name]>
    Default slot
  </template>
</foo>
複製代碼

簡單地說就是指令名,事件名,插槽名,都可以使用變數來定義了。

Tree-shaking

適用版本:Version: 3.x

在 vue 3 中不會把所有的 api 都打包進來,只會 打包你用到的 api

<!-- vue 2.x -->
import Vue from 'vue'

Vue.nextTick(() => {})

const obj = Vue.observable({})

<!-- vue 3.x -->
import Vue, { nextTick, observable } from 'vue'

Vue.nextTick // undefined

nextTick(() => {})

const obj = observable({})
複製代碼

即我們在項目中用什麼什麼,就只會打包什麼,不會像 vue 2.x 那樣全部 api 都打包。

.sync 大變樣

適用版本: vue 3.x

<!-- vue 2.x -->
<MyComponent v-bind:title.sync="title" />

<!-- vue 3.x -->
<MyComponent v-model:title="title" />
複製代碼

也就是說,vue 3.0 又去掉了 .sync ,合併到了 v-model 里,而 v-model 的內部實現也有了小調整

元素

<input v-model="xxx">

<!-- would be shorthand for: -->

<input
  :model-value="xxx"
  @update:model-value="newValue => { xxx = newValue }"
>

複製代碼

組件

<MyComponent v-model:aaa="xxx"/>

<!-- would be shorthand for: -->

<MyComponent
  :aaa="xxx"
  @update:aaa="newValue => { xxx = newValue }"
/>
複製代碼

不過好像組 alpha 版本的還不支持 v-model:aaa="xxx"

函數組件

適用版本: vue 3.x

<!-- vue 2.x -->
const FunctionalComp = {
  functional: true,
  render(h) {
    return h('div', `Hello! ${props.name}`)
  }
}
    
<!-- vue 3.x -->
import { h } from 'vue'
const FunctionalComp = (props, { slots, attrs, emit }) => {
  return h('div', `Hello! ${props.name}`)
}
複製代碼

不再需要 functional:true 選項,<template functional> 不再支付

非同步組件也必需通過 api 方法創建

import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() => import('./Foo.vue'))
複製代碼

全局 api

適用版本: vue 3.x

在 vue 2.x 中

import Vue from 'vue'
import App from './App.vue'

Vue.config.ignoredElements = [/^app-/]
Vue.use(/* ... */)
Vue.mixin(/* ... */)
Vue.component(/* ... */)
Vue.directive(/* ... */)

Vue.prototype.customProperty = () => {}

new Vue({
  render: h => h(App)
}).$mount('#app')
複製代碼

在 vue 3.x 中

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.config.isCustomElement = tag => tag.startsWith('app-')
app.use(/* ... */)
app.mixin(/* ... */)
app.component(/* ... */)
app.directive(/* ... */)

app.config.globalProperties.customProperty = () => {}

app.mount(App, '#app')
複製代碼

可以看到,創建實例的方式也改變了。一些全局的 api 方法也不在全局上了,而是放到了實例上。

更多的改變可以看這裡:github.com/vuejs/rfcs/…

v-model

適用版本:Version 3.x

1.原來的方式保留

<input v-model="foo">
複製代碼

2.可綁定多個 v-model

<InviteeForm
  v-model:name="inviteeName"
  v-model:email="inviteeEmail"
/>
複製代碼

其實上面這種方式就相當於之前的 .sync 。

3.額外處理

<Comp
   v-model:foo.trim="text"
   v-model:bar.number="number" />
複製代碼

我們可以給這個屬性添加額外的處理

指令的鉤子函數

適用版本:Version 3.x

在 vue 3.x 中 指令的鉤子函數仿照了組件中的鉤子函數命名規則

vue 2.x 時

const MyDirective = {
  bind(el, binding, vnode, prevVnode) {},
  inserted() {},
  update() {},
  componentUpdated() {},
  unbind() {}
}
複製代碼

vue 3.0 中

const MyDirective = {
  beforeMount(el, binding, vnode, prevVnode) {},
  mounted() {},
  beforeUpdate() {},
  updated() {},
  beforeUnmount() {}, // new
  unmounted() {}
}
複製代碼

transition

適用版本:Version 3.x

當 <transition> 作為組件的根元素時,外部切換不會觸發過渡效果

vue 2.x

<!-- modal component -->
<template>
  <transition>
    <div class="modal"><slot/></div>
  </transition>
</template>

<!-- usage -->
<modal v-if="showModal">hello</modal>
複製代碼

vue 3.x

<!-- modal component -->
<template>
  <transition>
    <div v-if="show" class="modal"><slot/></div>
  </transition>
</template>

<!-- usage -->
<modal :show="showModal">hello</modal>
複製代碼

也就是說我們只能在 <transition> 內使用切換。

transition-class

重命名兩個過渡類

v-enter 重命名成v-enter-fromv-leave重命名成 v-enter-from

.v-enter-from, .v-leave-to {
  opacity: 0;
}
.v-leave-from, .v-enter-to {
  opacity: 1
}
複製代碼

Router

適合版本:Version: Vue (2.x / 3.x) Vue Router (3.x / 4.x)

router-link 變動

router-link 添加 scoped-slot API 和 custom 屬性,並移除了 tag 屬性和 event 屬性。

添加 scoped-slot 有什麼用呢?以前只能通過 active-class 來改變元素樣式的,現在有了 scoped-slot 之後,我們就更加靈活了,可以根據 scoped-slot 回傳的狀態自定義,不管是樣式還是類。

<router-link to="/" custom v-slot="{ href, navigate, isActive }">
  <li :class="{ 'active': isActive }">
    <a :href="href" @click="navigate">
      <Icon>home</Icon><span class="xs-hidden">Home</span>
    </a>
  </li>
</router-link>
複製代碼

也就是說,新版本的 Router 就更加的純粹,只提供給我們一些參數,讓我們自己利用這些參數來實現不同的場景。

meta 合併

{
  path: '/parent',
  meta: { requiresAuth: true, isChild: false },
  children: [
    { path: 'child', meta: { isChild: true }}
  ]
}

複製代碼

當訪問 /parent/child 時,子路由中的 meta 如下:

{ requiresAuth: true, isChild: true }
複製代碼

合併策略與 Object.assign 類似

路由匹配所有

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  },
  {
    path: '/:catchAll(.*)',
    name: 'All',
    component: () => import(/* webpackChunkName: "All" */ '../views/Home.vue')
  }
]
複製代碼

這裡有一個需要註意的就是 vue-router 匹配所有路由的寫法已經改變了,不是舊版本的 * ,在新的版本里寫法參考上面的示例代碼

獲取當前路由信息

import router from '../router'
export default {
  setup () {
    const currentRoute = router.currentRoute.value
    console.log(currentRoute)
  }
}
複製代碼

引入的 router 為我們通過 createRouter() 方法創建的對象

import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
  history: createWebHashHistory(),
  routes
})
複製代碼

routes 路由為我們定義的路由數組,跟舊版本的一樣。

樣式 scoped

適用版本:Version: 2.x, 3.x

舊版本寫法

/* 深度選擇器 */
/*方式一:*/
>>> .foo{ }
/*方式二:*/
/deep/ .foo{ }
/*方式三*/
::v-deep .foo{ }
複製代碼

新版本寫法

/* 深度選擇器 */
::v-deep(.foo) {}
複製代碼

除了上面的深度選擇器外,還有下麵的兩個,寫法也差不多。

/* slot content 起作用 */
::v-slotted(.foo) {}

/* 全局 */
::v-global(.foo) {}
複製代碼

屬性值修正

適用版本:Version: 3.x

vue 本身會對元素的屬性作相應的處理。在舊版本的 vue 中處理如下:

表達式正常最終處理成
:attr="null" / draggable="false"
:attr="undefined" / /
:attr="true" foo="true" draggable="true"
:attr="false" / draggable="false"
:attr="0" foo="0" draggable="true"
attr="" foo="" draggable="true"
attr="foo" foo="foo" draggable="true"
attr foo="" draggable="true"

新版本處理方式:

表達式正常最終處理成
:attr="null" / /
:attr="undefined" / /
:attr="true" foo="true" draggable="true"
:attr="false" foo="false" draggable="false"
:attr="0" foo="0" draggable="0"
attr="" foo="" draggable=""
attr="foo" foo="foo" draggable="foo"
attr foo="" draggable=""

在新版本中基本保持了原樣,也就是我們給元素添加什麼屬性值,最好 vue 處理完後還是什麼屬性值。

非同步組件

import { defineAsyncComponent } from "vue"

// simple usage
const AsyncFoo = defineAsyncComponent(() => import("./Foo.vue"))
複製代碼

寫法上與之前有些不一樣。

動態路由

適用版本 Router 4

添加了幾個方法

  1. router.addRoute(route: RouteRecord) 動態添加路由
  2. router.removeRoute(name: string | symbol),動態刪除路由
  3. router.hasRoute(name: string | symbol): boolean ,判斷路由是否存在
  4. router.getRoutes(): RouteRecord[] 獲取路由列表
router.addRoute({
  path: '/new-route',
  name: 'NewRoute',
  component: NewRoute
})

// add to the children of an existing route
router.addRoute('ParentRoute', {
  path: 'new-route',
  name: 'NewRoute',
  component: NewRoute
})

router.removeRoute('NewRoute')

// normalized version of the records added
const routeRecords = router.getRoutes()
複製代碼

詳情可見:github.com/vuejs/rfcs/…

emits-option

const Foo = defineComponent({
  emits: {
    submit: (payload: { email: string; password: string }) => {
      // perform runtime validation
    }
  },

  methods: {
    onSubmit() {
      this.$emit('submit', {
        email: '[email protected]',
        password: 123 // Type error!
      })

      this.$emit('non-declared-event') // Type error!
    }
  }
})

複製代碼

現在的 $emit() 方法在用法上沒變,但需要額外多定義 emits 對象,但要註意的是現在 alpha 版本還不支持 TypeScript

組件根元素數量

vue 3 後組件不再限制 template 中根元素的個數(舊的版本之前是只能有一個根元素)。

vue 3.x 中費棄

  • beforeCreate、created
  • filters
  • keycode
  • inline-template
  • data-object
  • on,off 和 $once

1.閱讀完本文我相信你大概對 vue 3 有了一個基本的認識。雖然本文會不讓你瞬間成為 vue 3.x 的駕馭者,但怎麼說也讓你含蓄地體驗了一把 vue 3.x 的新特性。特別是 composition API 即使本文沒有詳細寫出來,但通過補充的鏈接,你也能閱讀到它的所有。我覺得 composition API 真的很棒。
2.光理論是不夠的。在此贈送2020最新企業級 Vue3.0/Js/ES6/TS/React/node等實戰視頻教程,想學的可進裙 519293536 免費獲取,小白勿進哦!

本文的文字及圖片來源於網路加上自己的想法,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理


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

-Advertisement-
Play Games
更多相關文章
  • 有一個 ? 遇到這樣一個疑問:當where查詢中In一個索引欄位作為條件,那麼在查詢中還會使用到索引嗎? SELECT * FROM table_name WHERE column_index in (expr) 上面的sql語句檢索會使用到索引嗎?帶著這個問題,在網上查找了很多文章,但是有的說 i ...
  • 概述 連接docker中的mysql終端(docker連接終端) 修改mysql配置 (vim使用和安裝) mysql大小寫簡單介紹 (庫名/錶面 欄位/內容 大小寫使用) docker下mysql終端操作(執行命令) 連接docker中的mysql終端 使用 查詢docker下的鏡像用來查看mys ...
  • 一、活動里的方法 (1)onCreate方法在活動創建之後必定執行的方法。 (2)Andorid程式講究​邏輯和視圖相分離; (3)setContentView()靜態方法,用於引入​視圖; (4)Android程式不推薦在程式中對字元串進行硬編碼​,最好的做法就是一般把字元串定義到res/valu ...
  • ##BindView ButterKnife 優勢 綁定組件方便,使用簡單 處理點擊事件方便,如adapter中的viewholder 同時父組件綁定後子組件無需綁定 註意 在setcontentview之後使用,且子空間不可再使用static final屬性 ##在不改變按鈕圖片大小的情況,擴大點 ...
  • 新聞 Android 11特性調整:安裝外部來源應用需要重啟APP Google Messages beta版迎來一個新的搜索框 Android開發者生態永遠比不上iOS?“聯盟與公約”們正改變這一點 谷歌新款Android TV串流設備外形曝光:代號Sabrina Android 11 Beta引 ...
  • 前言 大白(Baymax),迪士尼動畫《超能陸戰隊》中的健康機器人,是一個體型胖胖的充氣機器人,因呆萌的外表和善良的本質獲得大家的喜愛,被稱為“萌神”。 Baymax項目是為了減少開發人員在開發中一些不規範的代碼編寫造成的記憶體泄露,界面卡頓,耗電等問題而來的一個監控系統。 現在Baymax迎來了它新 ...
  • Vuex源碼閱讀(一) ,介紹Vuex的執行順序,以及new Vuex.Store()的時候內部都幹了什麼。 ...
  • 效果展示 頁面截圖 相關效果 預覽 html 頁面 從微信讀書上找了幾張書籍封面來做輪播的圖片。 index.html <body> <div id="container"> <div class="big_pic_div"> <div class="prev"></div> <div class= ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...