iT邦幫忙

0

Vue 模組化管理 自學筆記

今天我們要來利用模組化後的Vue來進行一些操作。
而組件的基本架構如下:

<template>
    模板
<h1 class="title"> {{ ... }}</h1>
</template>
<script>
     程式
export default {
    name:"titleData",
}
</script>
<style>
     樣式
</style>

首先我們想要創建一個能夠顯示Title的組件。

第一步就是要在App.vue中先引入他。


  // 要將component渲染到畫面上,首先要import進App.vue
  import Title from './components/Title.vue'

接著掛載在我們的components


    components: {
      HelloWorld,
      Title,
    },

最後將引入的組件加至template中。

<template>
  <div id="app">
    <Title titleData="hello jojo"/>
    <HelloWorld msg="Welcome to Your Vue.js App" />
      </div>
</template>

而我們在Title的組件中也要做一些處理。

模板的部分:

<template>
<h1 class="title"> {{ titleData }}</h1>
</template>

程式的部分:
data部分要用func型式,而不是物件(include作法),因為component會共用,如果直接做物件出來,每個component都會包到同一包資料,也就是會互相影響。

<script>
export default {
    name:"titleData",
     data() {
         return {
             title:"hello jojo"
         }
     },
<script>

每一個組件都是獨立的,我們無法直接從子組件獲取父組件的資料,而我們現在只想要這個模組顯示資料,而不用包含資料,也就是說資料是從父層傳過來,就要透過Props,而Props是單向的,只會從父層傳至子層,Props 的值也會因父層改變而改變。

<script>
export default {
    name:"titleData",
    // data() {
    //     return {
    //         title:"hello jojo"
    //     }
    // },
// 接收從外部(App.vue的 <Title/>)傳進來的資料titleData="hello jojo"
// 記得template中的資料也要改成titleData
    props:{
        // 給我一個titleData
        titleData:{
            // 類型是字串
            type:String,
            // required就是一定要
            required:true
        }
    }
}
</script>

樣式的部分:

為了不影響到其他組件,我們可以使用scoped,scoped可以將樣式封裝在當前模組,盡量不要直接搭配tag,要加上class,id,否則效能會較差,如果不加上scoped就會影響到其他component。

<style scoped>
    h1.title {
    color:#fa5
    }
</style>

加上scoped前(上圖),加上後(下圖)。
https://ithelp.ithome.com.tw/upload/images/20200728/20126182ab3c277Xjx.png

https://ithelp.ithome.com.tw/upload/images/20200728/20126182ZBIedEEyK2.png

而在App.vue的部分,我們除了可以直接傳遞資料外。

<template>
    // 利用直接傳遞資料的方法
    <Title titleData="hello jojo"/>
</template>

也可以利用綁定的方式來傳遞我們的資料,記得要將我們所要綁定的資料,在data函數中將值設置進去。

<template>
    // 利用資料綁定的方法傳遞資料
    <Title :titleData="bindData"/>
</template>

 export default {
    name: 'App',
    data() {
      return {
        bindData:"this is a bind msg"
      }
    },

除此之外,我們這邊再做一個input的組件,且當輸入框改變,畫面的資料也會同步跟著改變,而這個組件我們先創建一個資料夾,並分別創建template,vue,css。

https://ithelp.ithome.com.tw/upload/images/20200728/20126182bUpLOGoxJz.png

然後在父組件,按照創建組件的流程,引入組件、掛載組件、最後在套用組件。

將資料(bindData)傳入至子組件。

 <InputComponent :text="bindData"/>

而在子組件我們利用props接收父組件傳入的資料。

export default {
    name:"input-component",
    // 獲取的屬性及值
    props:{
        text:{
            type:String,
            required:true
        }
    }
}

template部分

<input
    type="text"
    v-model="text"
>

而後當我們改變input的值,會發現報錯,因為直接從子組件改變外部資料是不允許的,也就是說我們不能更動原資料(App.vue父層),因此我們寫一個computed來改變子層資料,並同步更新父層資料

computed的屬性可以被視為像是 data 一樣,可以讀取和設值,因此在computed中分成getter(讀取)setter(設值),在沒有寫 setter 的情況下,computed 預設為 getter,也就是只能讀取,不能改變設值getter 在大部分的時候是當內部觀察的資料有改變時會被觸發setter 則是當被觀察的物件本身有改變時會被觸發,也就是當我們改變輸入框的值時。

而在setter部分,可透過emit將子組件的資料傳遞至父組件,這邊我們傳遞一個事件textChange,並傳遞一個value
(子組件input當前的值)。

    computed: {
        inputText:{
            // 獲取值
            get(){
                console.log("get");
                return this.text
            },
            // 設置值
            set(value){
                console.log(value)
                // 子組件與父組件溝通的橋樑
                // this.$emit('event', […args])
                this.$emit('textChange', value)
            }
        }
    },

記得在template將綁定從 v-model="text" 改成inputText也就是我們包含兩個函數的 computed。

<input
    type="text"
    v-model="inputText"
>

子組件設置完成後,我們再回到父組件,接收從子層傳來的事件,並加上一個函數處理傳來的值。

    <InputComponent :text="bindData" @textChange="changeHandler" />

methods中處理子組件傳來的值,將其同步到父組件的資料。

    methods: {
      // 處理子層傳來的值(input中的值)
      changeHandler(value){
        // 將input中的值同步改變 bindData中的值
        this.bindData = value
      }
    },

而我們打開Vue Devtools,可發現我們的子組件本身都沒有資料,那資料在哪裡呢?都統一放在我們的父組件做管理,分給其他子組件使用,所以當我們在子組件改變輸入框的值,他會呼叫外部的資料,也就是父層的資料也進行改變,而父層的資料又會同步更新到畫面上。

https://ithelp.ithome.com.tw/upload/images/20200728/20126182wPblKHA2Jy.png


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言