2019年9月29日 星期日

[Vue] Prop

prop命名


  • Vue.component('myInput', ...) 等同於 Vue.component('my-input', ...)

prop類型

  • 預設寫法
 props: ['value']
  • 型別指定寫法
    props: {
        value: any,
        prefix: String,
        ...
    }

prop特性


  • 沒給值預設值為true
<my-input type="text" v-model="title" show-prefix>


Vue.component('myInput', {
    props: {
        value: String,
        prefix: String,
        showPrefix: Boolean
    },
...

單向資料流

  • 父組件的props更新後 => 更新子元件的props
  • 子組件的props更新不會 => 更新父組件的props
  • 不應該在子組件中變更props
  • 若props的型別為Object或Array,子組件變更時,會影響到父組件

prop驗證

  • 無驗證
props: {
    value: [String, Number]
}
  • 加入驗證
props: {
    value: {
        type: [String, Number],
        required: true, // 必填
        default: 'success', // 預設值
        // 自定義驗證
        validator: function (value) {
        // 這個值必須匹配下列字符串中的一個
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    },
    ...
}

type

可以是任一原生型別
  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol
也可以是自定義型別

class和style

從父組件給值時, 會和子組件合併
e.g.
  • 子組件
<input class="AAA">
  • 父組件
<my-input class="BBB">

最後渲染出來會是 <input class="AAA BBB">

2019年9月26日 星期四

[Vue] 組件註冊

組件名稱

  • Vue.component('組件名稱', {...})
  • 建議命名時
    • 全小寫
    • 用一個前缀詞加上hyphon符號(-), 避免和其他名稱重複
    • e.g. my-header

作用域

  • 全域註冊
註冊方式: Vue.component('組件名稱', {...})
  • 區域註冊
    • 好處: 在component沒被使用時,就不會被build,產生多餘的程式碼
    • 在子組件裡面也要使用的話,也需要在子組件中,再宣告一次

component宣告方式

const FooterComponent = {
    template: '<div>copyright @ blabalbala</div>'
}

根組件宣告方式

new Vue({
  ...
  components: {
    'my-footer': FooterComponent
  }
 ...
})

模塊系統

全域組件
  • 將各個component獨立成一個檔案,匯入匯出在根組件前載入
局部組件
  • 若有配合webpack或babel再深入研究
關鍵字: require, import

[Vue] 組件基礎 2/2

組件的HTML規則


  • 只能有一個根元素
e.g. 根結點不能二個元素並列, 一定要有明確的一個根結點
  • 不行:
<h1></h1>
<div></div>
  • 可以: (再包一層)
<div>

    <h1></h1>
    <div></div>
</div>
  • 模板字符串(``) 不支援IE, 需用折行轉譯字符代替
  • 不支援IE
Vue.component('component-name', {
template:`content
                line2
                line3`
}
  • 可支援IE
Vue.component('component-name', {
template:"content\
                line2\
                line3"
}

監聽子組件事件

子組件向外發出事件的方法
  • 子組件
Vue.component('my-header', {
    props: ['title'],
    template: `<div>
    <h1>{{title}}</h1>
    <button v-on:click="$emit('event-emit-test')">event emit</button>
</div>
    `
})
  • 父組件
<my-header title="Vue練習" @event-emit-test="catchClickCount+=1"></my-header>

*. $emit('事件名稱')
*. 接收方用事件名稱直接接收

監聽子組件事件(含參數傳遞)

  • 子組件
Vue.component('my-header', {
    props: ['title'],
    template: `<div>
    <h1>{{title}}</h1>
    <button v-on:click="$emit('event-emit-test',2)">event emit</button>
</div>
    `
})
  • 父組件
<my-header title="Vue練習" @event-emit-test="catchClickCount+=$event"></my-header>

v-model

v-model 就是一個bind和一個event組成的
  • 子組件
Vue.component('my-input', {
    props: ['value'],
    template: `
    <div>
    Hi~~~my input
    <input
        v-bind:value="value"
        v-on:input="$emit('input', $event.target.value)"
    />
    </div>
    `
})
  • 父組件
<my-input v-model="variableName"></my-input>

插槽(slot)

可在自定義的組建中預留空間, 讓父組件放置
  • 子組件
Vue.component('my-block', {
    template: `
    <div class="block">
        <slot></slot>
    </div>
    `
})
  • 父組件
<my-block>
    // 把內容裝進來
</my-block>

動態組件

<component v-bind:is="要綁定的組件"></component>
要綁定的組件有二種用法
  • 組件的名稱
  • 組件本身

其他關鍵字

  • vue is
is="這邊可塞入component"
  • 字符串 (例如:template: '...')
  • 單文件組件 (.vue)
  • <script type="text/x-template">

2019年9月25日 星期三

[Vue] 組件基礎 1/2

Vue的組件(Component)使用

  • 可透過 Vue.component 來自定義組件
Vue.component('counter', {
data: function () {
    return {
        count: 0
    }
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

  • 要在 new Vue({ el: '#app' }) 的作用愈中才能使用

<div id="app">
<counter></counter>
</div>

  • new Vue(...)中有的方法Vue.component(...)中絕大多數都有
    • e.g. data, computed, watch, methods 生命週期鉤子(life cycle hook)等
  • Vue.component(...)的data是函數

組件註冊

分為二種類型
  • 全域註冊
    • 顧名思義就是在根組件之下任何地方皆可使用
    • 透過 Vue.component(...)產生
  • 局部註冊

Prop

  • 傳入參數給組件
  • 可搭配v-for v-if ...等指令使用

2019年9月23日 星期一

[Vue] 表單輸入綁定

v-model

可用在
  • <input>
<input v-model="userName" placeholder="user name">
<p>User name is: {{userName}}</p>
  • <textarea>
<textarea v-model="remark" placeholder="remark"></textarea>
<p style="white-space: pre-line">{{remark}}</p>
  • <input type="checkbox"> 
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{checked}}</label>
  • group <input type="checkbox"> 
<input type="checkbox" id="memo1" value="memo1" v-model="checkedMemo">
<label for="memo1">Memo1</label>
<input type="checkbox" id="memo2" value="memo2" v-model="checkedMemo">
<label for="memo2">Memo2</label>
<input type="checkbox" id="memo3" value="memo3" v-model="checkedMemo">
<label for="memo3">Memo3</label>
<p>Checked Memo: {{checkedMemo}}</p>
  • <input type="radio">
<input type="radio" id="first" value="first" v-model="picked">
<label for="first">first</label>
<input type="radio" id="second" value="second" v-model="picked">
<label for="second">second</label>
<p>Picked: {{picked}}</p>
  • <select>
<select v-model="selected">
<option disabled value="">請選擇</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<p>Selected: {{selected}}</p>
  • group <select>
<select v-model="selected2" multiple>
<option disabled value="">請選擇</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<p>Selected: {{selected2}}</p>

修飾符

  • .lazy
    • onchange時才改變值
  • .number
    • 將值轉換為number, 轉換失敗變成預設值
  • .trim
    • 去除左右空白

[Vue] 事件處理

v-on

  • v-on:事件名稱="簡易邏輯"; e.g. v-on:click="total = total + 1"
  • v-on:事件名稱="自定義事件"; e.g. v-on:click="onClick"
  • v-on:事件名稱="自定義事件(傳入參數)"; e.g. v-on:click="doSomething(var1)"
  • v-on:事件名稱="自定義事件(傳入參數, $event)"; $event為原生DOM事件

事件修飾符

常見的修飾符
  • .stop
    • 停止propogation
    • event.stopPropagation()的意思
  • .prevent
    • 停止default event
    • event.preventDefault()的意思
  • .capture
    • 使用capture監聽事件
    • 由外而內觸發事件(預設是冒泡, 由內而外)
  • .self
    • 只處理單一層DOM的事件
  • .once
    • 只觸發一次事件
  • .passive
    • 被動監聽scroll

2019年9月19日 星期四

[Vue] 列表渲染

v-for

  • 可以額外顯示 index
  • in 可改 of

index.html

        <ul>
            <li v-for="(item, index) of items">
                {{item.message}}
            </li>
        </ul>

index.js

var app = new Vue({
    el: '#app',
    data: {
    items: [
         { message: 'message 1' },
        { message: 'message 2' }
    ]
}
})

v-for 可和 Object 一起使用

  • 可以額外顯示屬性名稱
  • 可以額外顯示 index
  • 順序是依照 Object.keys() 的順序, 不保證每個瀏覽器順序相同
  • 建議和 "key" 屬性相互搭配,, 避免順序變動時, 顯示異常

index.html

        <ul>
            <li v-for="(value, name) in object">
                {{value}}
            </li>
        </ul>

index.js

var app = new Vue({
    el: '#app',
    data: {
     object: {
         name: 'Shawn',
         sex: 'male',
         phone: '0912345678'
     }
}
})


2019年9月16日 星期一

[Vue] 條件渲染

v-if

  • 可搭配 v-else 使用
    • 必須緊跟在 v-if 或 v-else-if 之後
  • 也可搭配 v-else-if 使用
    • 必須緊跟在 v-if 之後
  • 可搭配<template>使用
    • 實際渲染時, 不會存在的元素

index.html

<div v-if="showHint">看情況顯示文字</div>

index.js

var app = new Vue({
    el: '#app',
    data: {
showHint: true
}
})

渲染機制

  • v-if, v-else 在使用時, 重複的內容"不會"重新渲染
  • 若要重新渲染, 應加上"key"屬性
  • 沒被加上key的元素, 依然會重複使用
        <div v-if="showHint">
            看情況顯示文字 <br>
            <input type="text" key="input1">
        </div>
        <div v-else>
            Hi v-else顯示 <br>
            <input type="text" key="input2">
        </div>

v-show

  • 單純的css display切換
  • DOM在一開始就會渲染

v-if , v-show

  • 頻繁的切換用 v-show
  • v-if 耗用的資源較多

v-if 和 v-for 同時使用

  • v-for先執行, v-if後執行
  • 官方不建議這樣使用

2019年9月15日 星期日

[Vue] Class與Style綁定

Class動態綁定(v-bind:class-name)

  • 動態class可和一般class共存
  • 可綁定一個或多個class
  • vue component 也可套用

index.html

        <div v-bind:class="{'name-block':true}">
            內容文字
<button @click="changeColor">Change background color</button>
        </div>

index.css

.name-block {
  background-colorantiquewhite;
  margin8px;
  padding8px;
}

.dark-theme {
  background-colorbrown;
  colorwhite;
}

index.js

var app = new Vue({
    el: '#app',
    data: {
isDark: false
},
methods: {
changeColor: function () {
            this.isDark = !this.isDark
        }
}
)

Class動態綁定 - 2

  • 可將整個class object放在javascript中

index.html

        <div class="block age-block" :class="classObject">
            你幾歲?
            <div>Reply: {{reply}}</div>
            <input type="text" v-model="age">
        </div>

index.css

.block {
  margin8px;
  padding8px;
}
.age-block {
  background-colorbisque;
}

index.js

var app = new Vue({
computed: {
        classObject: function () {
            return { 'dark-theme': this.isDark }
        }
    }
})

Inner Style動態綁定(v-bind:style-name)

  • 若有需要的話,vue會自動補上瀏覽器引擎前綴詞, e.g. transform

index.html

        <div class="block hello-world-block" :style="{fontSize: fontSize + 'px'}">
            <input type="text" v-model="title">
            <div>{{title}}</div>
            <div>Reverse Title: {{reverseTitle}}</div>
        </div>

index.css

.hello-world-block {
  background-colorburlywood;
}

index.js

var app = new Vue({
    el: '#app',
    data: {
     fontSize: 30
}
})