亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

前言

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

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

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

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

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

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

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

基礎(chǔ)實(shí)現(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>

效果:

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

mixin

簡(jiǎn)單來(lái)說(shuō),mixin允許我們提供一個(gè)或多個(gè)像普通實(shí)例對(duì)象一樣包含實(shí)例選項(xiàng)的對(duì)象,Vue.js會(huì)以一定的邏輯自動(dòng)合并這些對(duì)象里面的選項(xiàng)和組件的選項(xiàng)。舉例來(lái)說(shuō),如果你的 mixin 包含了一個(gè) created 鉤子,而組件自身也有一個(gè),那么這兩個(gè)函數(shù)都會(huì)被調(diào)用。本文不再贅述,請(qǐng)參考Vue.js——mixins。以下就是通過(guò)mixin實(shí)現(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>

效果與之前的一致。

我們來(lái)分析下mixin的缺點(diǎn):

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

高階組件

所謂高階組件,就是通過(guò)實(shí)現(xiàn)一個(gè)包裝函數(shù),這個(gè)包裝函數(shù)返回像普通實(shí)例對(duì)象一樣包含實(shí)例選項(xiàng)的對(duì)象,該對(duì)象內(nèi)包含render選項(xiàng),render用于渲染內(nèi)部的組件,并將屬性通過(guò)props注入到內(nèi)部組件。比如我們可以像下面這樣通過(guò)高階組件復(fù)用這個(gè)鼠標(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>

我們?cè)賮?lái)分析下,用高階組件來(lái)實(shí)現(xiàn)邏輯復(fù)用,是不是就沒(méi)有缺點(diǎn)呢?

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

作用域插槽(scoped slots)

作用域插槽(scoped slots)這種方式和高階組件有點(diǎn)像,區(qū)別在于不是通過(guò)函數(shù)來(lái)包裹,而是通過(guò)實(shí)現(xiàn)一個(gè)組件來(lái)包裹,我們叫它父組件,在父組件實(shí)現(xiàn)需要復(fù)用的邏輯,使用作用域插槽,將父組件的狀態(tài)共享給子組件。代碼實(shí)現(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)
    },
    // 等價(jià)于 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>

我們還是來(lái)分析下這種方式的優(yōu)缺點(diǎn),還是通過(guò)假設(shè)我們需要重用多個(gè)邏輯,把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è)問(wèn)題了,我們能夠很明顯的看到每個(gè)屬性是從哪個(gè)組件注入的,來(lái)源清晰了,即使有命名的問(wèn)題,我們?cè)诮鈽?gòu)的時(shí)候是可以重命名避免的,比如Foo注入的也叫x,那我們可以這么寫<Foo v-slot="{ x: foo }">。

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

Composition API 組合式函數(shù)

先簡(jiǎn)單介紹下Composition API

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

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

接著我們用Composition API來(lái)實(shí)現(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>

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

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

能直接返回useMouseMove()嗎

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

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

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

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

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

最佳實(shí)踐

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

總結(jié)

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

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

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

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

相關(guān)文章

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

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

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

    VUE2實(shí)現(xiàn)事件驅(qū)動(dòng)彈窗示例

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

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

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

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

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

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

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

    詳解vue移動(dòng)端項(xiàng)目的適配(以mint-ui為例)

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

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

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

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

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

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

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

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

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

最新評(píng)論