欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

4種方案帶你探索Vue代碼復(fù)用的前世今生

 更新時間:2023年05月30日 09:30:47   作者:Lvzl  
我們所熟知的Vue.js也在如何提取公共代碼復(fù)用方面也一直在探索優(yōu)化,本文小編就來和各位聊聊Vue.js代碼復(fù)用的前世今生,希望對大家學(xué)習(xí)Vue有一定的幫助

前言

在我們平時開發(fā)中,不論你使用什么語言,當(dāng)遇到了大量的重復(fù)代碼,我們可能會去將重復(fù)代碼提取出來,獨立一個模塊,在多個地方引用,這是一個好習(xí)慣,是值得推薦的!當(dāng)然也有些同學(xué)不感冒,使用到了直接CV,撇開代碼規(guī)范設(shè)計模式這些不談,往往CV會給你帶來更大的工作量(比如用了很多地方,你要去CV很多地方,如果后續(xù)有變動,你又要重復(fù)CV到很多地方......,當(dāng)然不推薦CV)。我們所熟知的Vue.js也在如何提取公共代碼復(fù)用方面也一直在探索優(yōu)化,本文筆者就來和各位聊聊Vue.js代碼復(fù)用的前世今生。

在Vue.js中我們可通過以下4種方案來實現(xiàn)代碼邏輯復(fù)用

  • mixin
  • 高階組件
  • 作用域插槽(scoped slots)
  • Composition API 組合式函數(shù)

可能各位常用的是mixin,沒關(guān)系,其他幾種也很好理解。筆者會通過一個實際的案例分別使用以上的方案實現(xiàn),并分析各種方案的優(yōu)缺點來帶各位掘友體會Vue.js代碼邏輯復(fù)用方面的優(yōu)化歷程。

案例:就以大家所熟知的 鼠標(biāo)位置 來吧

Vue.js 代碼邏輯復(fù)用

我們先不考慮復(fù)用,先來看看如何實現(xiàn)鼠標(biāo)位置這個功能,功能十分簡單,大家肯定都會,筆者就不廢話了,直接看下代碼吧:

基礎(chǔ)實現(xiàn)

<script src="https://unpkg.com/vue@next"></script>
<div id="app"></div>
<script>
  const { createApp } = Vue
  const App = {
    template: `{{x}}  {{y}}`,
    data() {
      return {
        x: 0,
        y: 0
      }
    },
    methods: {
      handleMouseMove(e) {
        this.x = e.pageX
        this.y = e.pageY
      }
    },
    mounted() {
      window.addEventListener('mousemove', this.handleMouseMove)
    },
    unmounted() {
      window.removeEventListener('mousemove', this.handleMouseMove)
    }
  }
  createApp(App).mount('#app')
</script>

效果:

接下來,我們嘗試將這個功能提取以達到復(fù)用的目的,先來看看 mixin 這個方案。

mixin

簡單來說,mixin允許我們提供一個或多個像普通實例對象一樣包含實例選項的對象,Vue.js會以一定的邏輯自動合并這些對象里面的選項和組件的選項。舉例來說,如果你的 mixin 包含了一個 created 鉤子,而組件自身也有一個,那么這兩個函數(shù)都會被調(diào)用。本文不再贅述,請參考Vue.js——mixins。以下就是通過mixin實現(xiàn)復(fù)用MouseMove的邏輯:

<script>
  const { createApp } = Vue
  const MouseMoveMixin = {
    data() {
      return {
        x: 0,
        y: 0
      }
    },
    methods: {
      handleMouseMove(e) {
        this.x = e.pageX
        this.y = e.pageY
      }
    },
    mounted() {
      window.addEventListener('mousemove', this.handleMouseMove)
    },
    unmounted() {
      window.removeEventListener('mousemove', this.handleMouseMove)
    }
  }
  const App = {
    template: `{{x}}  {{y}}`,
    mixins: [ MouseMoveMixin ]
  }
  createApp(App).mount('#app')
</script>

效果與之前的一致。

我們來分析下mixin的缺點:

  • 當(dāng)我們的組件有多個mixin,比如:mixins: [ MouseMoveMixin, anthorMixin, fooMixin ],我們就會分不清哪些變量是從MouseMoveMixin來的?哪些變量是從anthorMixin來的?那就出現(xiàn)了第一個缺點:變量來源不清
  • 同樣的,當(dāng)我們的組件有多個mixin,我們不得不去考慮他們注入的變量名會不會存在沖突。那就出現(xiàn)了第二個缺點:命名沖突

高階組件

所謂高階組件,就是通過實現(xiàn)一個包裝函數(shù),這個包裝函數(shù)返回像普通實例對象一樣包含實例選項的對象,該對象內(nèi)包含render選項,render用于渲染內(nèi)部的組件,并將屬性通過props注入到內(nèi)部組件。比如我們可以像下面這樣通過高階組件復(fù)用這個鼠標(biāo)位置的邏輯。

<script>
  const { createApp, h } = Vue
  // 包裝函數(shù)
  function withMouse(inner) {
    return {
      data() {
        return {
          x: 0,
          y: 0
        }
      },
      methods: {
        handleMouseMove(e) {
          this.x = e.pageX
          this.y = e.pageY
        }
      },
      mounted() {
        window.addEventListener('mousemove', this.handleMouseMove)
      },
      unmounted() {
        window.removeEventListener('mousemove', this.handleMouseMove)
      },
      render() {
        // 注入 x, y
        return h(inner, { x: this.x, y: this.y })
      }
    }
  }
  const App = withMouse({
    template: `{{x}}  {{y}}`,
    props: ['x', 'y']
  })
  createApp(App).mount('#app')
</script>

我們再來分析下,用高階組件來實現(xiàn)邏輯復(fù)用,是不是就沒有缺點呢?

同樣的,我們還是假設(shè)我有還多塊邏輯要復(fù)用,比如把mixins: [ MouseMoveMixin, anthorMixin, fooMixin ]改寫成高階組件,那將變成以下代碼:

  function withMouse(inner) {
    // 此處省略
  }
  function withFoo(inner) {
    // 此處省略
  }
  function withAnthor(inner) {
    // 此處省略
  }
  const App = withAnthor(withFoo(withMouse({
    template: `{{x}}  {{y}}`,
    props: ['x', 'y', 'foo', 'anthor']
  })))
  createApp(App).mount('#app')

mixin的問題它都有,props中我們依然看不清哪些屬性是由哪個高階組件注入的,也依然不得不考慮命名沖突的問題。(有些同學(xué)可能覺得,如果注入的變量名能夠和包裹函數(shù)名有聯(lián)系,那就能夠看出來。那確實是的,但是這就需要有很嚴(yán)格的開發(fā)規(guī)范代碼走查來約束開發(fā)人員了)顯然高階組件也不是什么”靈丹妙藥“,我們接著看如何使用scoped slots來實現(xiàn)這個邏輯復(fù)用。

作用域插槽(scoped slots)

作用域插槽(scoped slots)這種方式和高階組件有點像,區(qū)別在于不是通過函數(shù)來包裹,而是通過實現(xiàn)一個組件來包裹,我們叫它父組件,在父組件實現(xiàn)需要復(fù)用的邏輯,使用作用域插槽,將父組件的狀態(tài)共享給子組件。代碼實現(xiàn)如下:

<script>
  const { createApp } = Vue
  const MouseMove = {
    data() {
      return {
        x: 0,
        y: 0
      }
    },
    methods: {
      handleMouseMove(e) {
        this.x = e.pageX
        this.y = e.pageY
      }
    },
    mounted() {
      window.addEventListener('mousemove', this.handleMouseMove)
    },
    unmounted() {
      window.removeEventListener('mousemove', this.handleMouseMove)
    },
    // 等價于 template: `<slot :x="x" :y="y"></slot>`,
    render() {
      return this.$slots.default && this.$slots.default({
        x: this.x,
        y: this.y
      })
    }
  }
  const App = {
    template: `<MouseMove v-slot="{x, y}">{{x}}  {{y}}</MouseMove>`,
    components: { MouseMove }
  }
  createApp(App).mount('#app')
</script>

我們還是來分析下這種方式的優(yōu)缺點,還是通過假設(shè)我們需要重用多個邏輯,把mixins: [ MouseMoveMixin, anthorMixin, fooMixin ]改寫為使用作用域插槽:

  const MouseMove = {
  }
  const Foo = {
  }
  const Anthor = {
  }
  const App = {
    template: `
    <MouseMove v-slot="{ x, y }">
      <Foo v-slot="{ foo }">
        <Anthor v-slot="{ anthor }">
          {{x}} {{y}} {{foo}} {{anthor}}
        </Anthor>
      </Foo>
    </MouseMove>`,
    components: { MouseMove, Foo, Anthor }
  }
  createApp(App).mount('#app')

看上去是解決了上面兩個問題了,我們能夠很明顯的看到每個屬性是從哪個組件注入的,來源清晰了,即使有命名的問題,我們在解構(gòu)的時候是可以重命名避免的,比如Foo注入的也叫x,那我們可以這么寫<Foo v-slot="{ x: foo }">。

那是不是這樣就完美了呢?并沒有,細(xì)心的同學(xué)可能發(fā)現(xiàn)了,我們?yōu)榱藦?fù)用邏輯導(dǎo)致了更多的組件實例創(chuàng)建,是不是有點魚和熊掌不可兼得的感覺,我們接下來看Vue.js的終極大招——Composition API 組合式函數(shù)

Composition API 組合式函數(shù)

先簡單介紹下Composition API

組合式 API (Composition API) 是一系列 API 的集合,使我們可以使用函數(shù)而不是聲明選項的方式書寫 Vue 組件。它包含了這些API:

  • 響應(yīng)式API —— ref、reactive computed、watch......
  • 生命周期鉤子 —— onMounted、onUnmounted......
  • 依賴注入 —— provide、inject......

接著我們用Composition API來實現(xiàn)一下:

<script>
  const { createApp, ref, onMounted, onUnmounted } = Vue
  function useMouseMove() {
    const x = ref(0)
    const y = ref(0)
    const handleMouseMove = e => {
      x.value = e.pageX
      y.value = e.pageY
    }
    onMounted(() => {
      window.addEventListener('mousemove', handleMouseMove)
    })
    onUnmounted(() => {
      window.removeEventListener('mousemove', handleMouseMove)
    })
    return { x, y }
  }
  const App = {
    setup() {
      const { x, y } = useMouseMove()
      return { x, y }
    },
    template: `{{x}} {{y}}`,
  }
  createApp(App).mount('#app')
</script>

看完這個實現(xiàn),首先它肯定是沒有以上的各種問題的,同時Composition API也是Vue3的一個重大更新,能夠讓我們更輕松的組織我們的邏輯代碼,更輕松的達到邏輯復(fù)用,可謂是完美方案!

可能你還有點小問題,比如setup為啥要先解構(gòu),再返回 { x, y }。

能直接返回useMouseMove()嗎

  const App = {
    setup() {
      return useMouseMove()
    },
    template: `{{x}} {{y}}`,
  }

答:如果你沒有其他變量需要暴露出去,你當(dāng)然可以直接返回useMouseMove()。但是直接返回useMouseMove(),那又回到了之前的問題,又不能清晰地看出哪個變量是哪個組合式函數(shù)注入的。

我能不能在return的對象里解構(gòu)

  const App = {
    setup() {
      return {
        ...useMouseMove()
      }
    },
    template: `{{x}} {{y}}`,
  }

答:可以,但不推薦,這么寫還是又回到了之前的問題。

最佳實踐

  const App = {
    setup() {
      const { x, y } = useMouseMove()
      return { x, y }
    },
    template: `{{x}} {{y}}`,
  }

總結(jié)

本文用Vue.js四種邏輯復(fù)用的方案實現(xiàn)了 鼠標(biāo)位置 的例子,并且分析了每種方案的優(yōu)缺點。

  • mixin —— 存在 命名沖突、變量來源不清
  • 高階組件 —— 存在 命名沖突、變量來源不清
  • 作用域插槽(scoped slots)—— 為了邏輯復(fù)用導(dǎo)致更多組件實例創(chuàng)建,得不償失
  • Composition API 組合式函數(shù) —— 完美方案

相信讀完本文,你一定學(xué)到了在Vue.js搭建的應(yīng)用中實現(xiàn)代碼邏輯復(fù)用的最佳姿勢!

以上就是4種方案帶你探索Vue代碼復(fù)用的前世今生的詳細(xì)內(nèi)容,更多關(guān)于Vue代碼復(fù)用的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue的常用組件操作方法應(yīng)用分析

    vue的常用組件操作方法應(yīng)用分析

    這篇文章主要介紹了vue的常用組件操作方法應(yīng)用分析,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-04-04
  • VUE2實現(xiàn)事件驅(qū)動彈窗示例

    VUE2實現(xiàn)事件驅(qū)動彈窗示例

    本篇文章主要介紹了VUE2實現(xiàn)事件驅(qū)動彈窗示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Vue+FormData+axios實現(xiàn)圖片上傳功能的項目實戰(zhàn)

    Vue+FormData+axios實現(xiàn)圖片上傳功能的項目實戰(zhàn)

    本文主要介紹了Vue+FormData+axios實現(xiàn)圖片上傳功能的項目實戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Vue.js集成Word實現(xiàn)在線編輯功能

    Vue.js集成Word實現(xiàn)在線編輯功能

    在現(xiàn)代Web應(yīng)用中,集成文檔編輯功能變得越來越常見,特別是在協(xié)作環(huán)境中,能夠直接在Web應(yīng)用內(nèi)編輯Word文檔可以極大地提高工作效率,本文將詳細(xì)介紹如何在Vue.js項目中集成Word在線編輯功能,需要的朋友可以參考下
    2024-08-08
  • vue父組件值變化但子組件不刷新的三種解決方案

    vue父組件值變化但子組件不刷新的三種解決方案

    父組件傳遞給子組件的數(shù)據(jù),如果是一個復(fù)雜對象(例如一個數(shù)組或?qū)ο螅?那么子組件只會監(jiān)聽對象的引用而不是對象的內(nèi)容,這意味著當(dāng)對象的內(nèi)容發(fā)生變化時,子組件不會更新,本文給大家介紹了vue子組件不刷新的三種解決方案,需要的朋友可以參考下
    2024-03-03
  • 詳解vue移動端項目的適配(以mint-ui為例)

    詳解vue移動端項目的適配(以mint-ui為例)

    這篇文章主要介紹了詳解vue移動端項目的適配(以mint-ui為例),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • karma+webpack搭建vue單元測試環(huán)境的方法示例

    karma+webpack搭建vue單元測試環(huán)境的方法示例

    本篇文章主要介紹了karma+webpack搭建vue單元測試環(huán)境的方法示例,這次搭建的測試環(huán)境和開發(fā)環(huán)境隔離,所以理論上適用所有使用vue的開發(fā)環(huán)境。感興趣的小伙伴們可以參考一下
    2018-05-05
  • el-date-picker日期范圍限制的實現(xiàn)

    el-date-picker日期范圍限制的實現(xiàn)

    本文主要介紹了el-date-picker日期范圍限制的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Vue?打包優(yōu)化之externals抽離公共的第三方庫詳解

    Vue?打包優(yōu)化之externals抽離公共的第三方庫詳解

    這篇文章主要為大家介紹了Vue?打包優(yōu)化之externals抽離公共的第三方庫詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪<BR>
    2023-06-06
  • Vue-cli3項目引入Typescript的實現(xiàn)方法

    Vue-cli3項目引入Typescript的實現(xiàn)方法

    這篇文章主要介紹了Vue-cli3項目引入Typescript的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10

最新評論