iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0
Vue.js

業主說給你30天學會Vue系列 第 17

V17_Vue的不同語法的對照Composition_API及Options_API

  • 分享至 

  • xImage
  •  

V17_Vue的不同語法的對照Composition_API及Options_API

從官網的介紹會發現有2種API,Composition API及 Options API
還有 SFC模式及 HTML模式

今天來學習這些不同的組合,以便在查看Vue的程式時,不會侷限在單一的語法

先從簡單的範例來看出這些語法的差別
參考Vue官網的 Handling User Input 的範例
https://vuejs.org/examples/#handling-input

首先是 熟悉的 Composition+SFC
App.vue

<script setup>
import { ref } from 'vue'

const message = ref('Hello World!')

function reverseMessage() {
  message.value = message.value.split('').reverse().join('')
}

function notify() {
  alert('navigation was prevented.')
}
</script>

<template>
  <h1>{{ message }}</h1>
  <button @click="reverseMessage">Reverse Message</button>
  <button @click="message += '!'">Append "!"</button>
  <a href="https://vuejs.org" @click.prevent="notify">
    A link with e.preventDefault()
  </a>
</template>

<style>
button, a {
  display: block;
  margin-bottom: 1em;
}
</style>

這個程式,先從<template>看起
有2個 <button>綁定了 @click 的事件,分別執行 reverseMessagemessage += '!'
reverseMessage是一個function

function reverseMessage() {
  message.value = message.value.split('').reverse().join('')
}

執行的結果 是將 變數message的內容 message.value從反向排列的處理
message += '!' 是 inline的程式碼,所以不用寫成 message.value 而是 message就可以了

message再綁定到 <h1>的內容 {{ message }}
const message = ref('Hello World!') 使用ref('Hello World!')進行綁定,初值是 'Hello World!'

最後是 <a> 綁定了 @click.preven的事件 這裡使用 click.prevent 是指在click的時候,
不會開啓 超連結的網址,就是將原本預設的動作 prevent 停止掉,改以執行 notify的function

function notify() {
  alert('navigation was prevented.')
}

則是開啟一個alert視窗

由以上的說明,我個人覺得 Composition+SFC的組合是最簡潔好理解的語法
只是這個需要透過vue+vite build之後才能在網站上執行

因此,若想要直接在HTML上不經過build說可以執行的話
就要使用 Composition+HTML 的組合

//-----------------------------------------------------
再來是 Composition+HTML
index.html

<script type="module">
import { createApp, ref } from 'vue'

createApp({
  setup() {
    const message = ref('Hello World!')

    function reverseMessage() {
      message.value = message.value.split('').reverse().join('')
    }

    function notify() {
      alert('navigation was prevented.')
    }

    return {
      message,
      reverseMessage,
      notify
    }
  }
}).mount('#app')
</script>

<div id="app">
  <h1>{{ message }}</h1>
  <button @click="reverseMessage">Reverse Message</button>
  <button @click="message += '!'">Append "!"</button>
  <a href="https://vuejs.org" @click.prevent="notify">
    A link with e.preventDefault()
  </a>
</div>

style.css

button, a {
  display: block;
  margin-bottom: 1em;
}

這個組合 是直接使用HTML+CSS
樣式的部份分開到 style.css
主網頁的部份 index.html

原本的<template>改成 <div id="app">
<template> 的內容跟 <div id="app"> 是相同的,
不一樣的是在 script 的部份

原本的 <script setup> 改成 <script type="module">
<script type="module">
使用 createApp({ setup(){} }).mount('#app') 的結構

其中 setup(){} 像是 <script setup> 中的setup一般

setup()中,

const message = ref('Hello World!')

function reverseMessage() {
  message.value = message.value.split('').reverse().join('')
}

function notify() {
  alert('navigation was prevented.')
}

return {
  message,
  reverseMessage,
  notify
}

變數 message 宣告綁定的方式一樣,但要多寫 return 的部份
等於是有綁定到的變數,功能都要列出來

setup(){} 像是在設定 setup() 的功能
就像 在 <script setup> 內設定一樣

參考一下官網上的說明

import { createApp } from 'vue'
const app = createApp(/* ... */)

app.mount('#app')

所以 createApp({ setup(){} })的部份中的 createApp({}) 是 vue的預設功能

const app = createApp({}); 先產生一個vue物件,然後再透過
app.mount('#app') 掛載到 <div id="app">

其中 createApp({ setup(){} }) 可以理解為
createApp() 中輸入一個物件 {},物件中設定一個 setup(){} 的函式或功能
setup(){} 中,宣告vue元件或物件需要的各種變數及功能

其實在 Composition+SFC 組合中
只是將 <script type="module">,<div id="app">,<style> 整合到 App.vue上
最基本的index.html還是有的

附帶列出來對照一下
index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

/src/main.js

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

createApp(App).mount('#app')

App.vue

<script setup>
import { ref } from 'vue'
const msg = ref('Hello World!')
</script>

<template>
  <h1>{{ msg }}</h1>
  <input v-model="msg">
</template>

因此,變成可以專心在 App.vue 上設計就可以了

若是網頁式的
index.html

<style>
button, a {
  display: block;
  margin-bottom: 1em;
}
</style>

<script type="module">
import { createApp, ref } from 'vue'

createApp({
  setup() {
    const msg = ref('Hello World!')

    return {
      msg
    }
  }
}).mount('#app')
</script>

<div id="app">
  <h1>{{ msg }}</h1>
  <input v-model="msg">
</div>

基本上,還是使用 Composition API的模式
只是 createApp({ setup(){} })<script setup>的差別

//-----------------------------------------------------
再來是 Options+SFC
App.vue

<script>
export default {
  data() {
    return {
      message: 'Hello World!'
    }
  },
  methods: {
    reverseMessage() {
      this.message = this.message.split('').reverse().join('')
    },
    notify() {
      alert('navigation was prevented.')
    }
  }
}
</script>

<template>
  <h1>{{ message }}</h1>
  <button @click="reverseMessage">Reverse Message</button>
  <button @click="message += '!'">Append "!"</button>
  <a href="https://vuejs.org" @click.prevent="notify">
    A link with e.preventDefault()
  </a>
</template>

<style>
button, a {
  display: block;
  margin-bottom: 1em;
}
</style>

Options+SFC的組合 <template><style>不變
主要是<script> 的部份

export default { } 可以看作是 原本的 <script setup> 或是 setup(){}

  data() {
    return {
      message: 'Hello World!'
    }
  },

算是設定了data()的函式,return回傳 綁定的 變數message,及初值 'Hello World!'
至於 data(){ return { } } 就可看作是與 <template> 綁定的介面

對應的是 變數宣告的部份
const message = ref('Hello World!')

  methods: {
    reverseMessage() {
      this.message = this.message.split('').reverse().join('')
    },
    notify() {
      alert('navigation was prevented.')
    }
  }

函式的宣告設定,則是要在 methods: { } 的屬性中設定
每個函式的宣告,要用 逗號分開
像是物件中的函式宣告

對應 Composition API的語法,在<script setup>
變數及函式的宣告,都是獨立設定的

Options的語法上,主要是使用物件的語法

整個來看,可以理解為
export default{} 代表產出一個 物件,像是 createApp({}) 產出App物件一般
這個 default 物件 就像 App.vue 會被 import App from './App.vue' 匯入一樣
這個 App 就是這個 default 物件

Composition APIOptions API 之間的語法差異
可以整理出一個對照表,網路上可以找到很多資料

補充一下,在網路上有看到 Composition API 也有 export default 的語法

<script>
import { ref } from 'vue'

export default {
  setup() {
    const message = ref('Hello World!')

    const reverseMessage = () => {
      message.value = message.value.split('').reverse().join('')
    }

    const notify = () => {
      alert('navigation was prevented.')
    }

    return {
      message,
      reverseMessage,
      notify
    }
  }
}

</script>

這很像後來的 Composition API+HTML <script type="module"> 模式

<script type="module">
import { createApp, ref } from 'vue'

createApp({
  setup() {
    const message = ref('Hello World!')

    function reverseMessage() {
      message.value = message.value.split('').reverse().join('')
    }

    function notify() {
      alert('navigation was prevented.')
    }

    return {
      message,
      reverseMessage,
      notify
    }
  }
}).mount('#app')
</script>

export default { setup() { } } -> (<script>)
變成 createApp({ setup() { } } -> (<script type="module">)
最後再變成 <script setup> 模式

我相信這些都是Vue在改進或改版的過渡過程
到目前為止,

Composition API+SPC <script setup>會是最佳的狀態

我覺得因為版本的語法差異還不小,容易造成學習上的混淆
如果都以最新版的來對照學習,就可以快速的掌握vue的重點

//-----------------------------------------------------
最後是 Options+HTML
index.html

<script type="module">
import { createApp } from 'vue'

createApp({
  data() {
    return {
      message: 'Hello World!'
    }
  },
  methods: {
    reverseMessage() {
      this.message = this.message.split('').reverse().join('')
    },
    notify() {
      alert('navigation was prevented.')
    }
  }
}).mount('#app')
</script>

<div id="app">
  <h1>{{ message }}</h1>
  <button @click="reverseMessage">Reverse Message</button>
  <button @click="message += '!'">Append "!"</button>
  <a href="https://vuejs.org" @click.prevent="notify">
    A link with e.preventDefault()
  </a>
</div>

style.css

button, a {
  display: block;
  margin-bottom: 1em;
}

有了上述的分析 在看到這個組合時,就等於是直接看懂了

結論就是

Composition API+SFC <script setup>
Composition API+HTML <script type="module">

循著這樣的規律,有了整體的觀念後,剩下的就是各個細部的功能學習
以及 利用範例及專案練功了


上一篇
V16_從Vue的範例做中學(2)_Fetching_Data
下一篇
V18_Vue的Composition_API的功能清單
系列文
業主說給你30天學會Vue31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言