Vue (1) - 環境建立、指令與修飾符

環境建立

Vue 的載入有 2 個版本,可以使用官網提供的 CDN 快速引入:

開發版本- 包含開發者工具、完整的警告、錯誤提示,適合開發時使用
生產版本- 刪除了警告,將上述開發工具都拔除,盡量縮小它的體積,適合正式發布時使用。

為了學習 Vue 的開發,因此我們選擇開發版本,並且在 script 標籤引入 vue.js 即可。

1
2
3
4
5
6
7
8
<head>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<script>
//這樣這裡就可以準備撰寫vue的檔案啦!
</script>
</body>

建立 Vue 應用程式

建立 Vue 的應用程式,通常是以 id 來命名 (ex:app),並且在 javascript 的地方以 new 初始化 vue,裡面放入一個物件,以 el 指定剛才命名的 id app,這裡的 el 名稱,就是與後面 HTML 綁定的 id 名稱相同。

同時,在應用程式生成之後,必須綁定一個 HTML 元素。並在 data 建立一個物件放入資料,接著在 html 元素中以兩層花括號的方式指定要顯示的資料名稱,接著就會在畫面上呈顯出資料的部分。範例如下:

  • HTML 部份
1
2
3
<div id='app'>
{{text}}
</div>
  • JavaScript 部份
1
2
3
4
5
6
var app = new Vue({
el: "#app",
data: {
text: 'some words'
}
});

不可建立巢狀應用程式

要注意 Vue 雖然可以在同一個頁面建立多個應用程式,但是不能建立如下的巢狀結構,否則第二個應用程式會無效

  • HTML 部份
1
2
3
4
5
6
7
8
<div id='app'>
{{text}}

<div id='app2'>
{{text2}}
</div>

</div>
  • JavaScript 部份
1
2
3
4
5
6
7
8
9
10
11
12
13
var app = new Vue({
el: "#app",
data: {
text: 'some words'
}
});

var app2 = new Vue({
el: "#app2",
data: {
text2: 'some words'
}
});

MVVM 與雙向自動綁定

Vue 是受 MVVM 風格啟發的一套雙向數據綁定的 Javascript 框架。MVVM 是一種軟體架構模式

它的核心只關心視圖層 (View),它的核心是 MVVM 中的 VM,也就是 ViewModel。ViewModel 負責連接 View 和 Model,保證視圖和數據的一致性。但我們在使用 Vue 的時候,只會利用 修改 Model 來影響視圖,是以資料狀態操作畫面,與例如 jQuery 以操作 DOM 方式改變畫面的方式不同。

  • 模型
    模型是指代表真實狀態內容的領域模型(物件導向),或指代表內容的資料存取層(以資料為中心)。
  • 視圖
    就像在 MVC 和 MVP 模式中一樣,視圖是用戶在螢幕上看到的結構、布局和外觀(UI)。
  • 視圖模型
    視圖模型是暴露公共屬性和命令的視圖的抽象。MVVM 沒有 MVC 模式的控制器,也沒有 MVP 模式的 presenter,有的是一個繫結器。在視圖模型中,繫結器在視圖和資料繫結器之間進行通訊。
  1. 使用雙花括號與資料串接
  2. 使用 v-model 綁定 HTML 屬性
  3. 使用 v-text 直接將資料寫入畫面
  4. 使用 v-html 除了將資料寫入畫面,還可修改 HTML 結構
1
2
3
4
5
6
- HTML 部份
<div id="app">
{{message}}
<div v-html="message"></div>
<input type="text" v-model="message">
</div>
1
2
3
4
5
6
7
8
9
10
11
12
- JavaScript 部份

<script>
var app = new Vue({
el: '#app',
// 在此建立資料內容

data: {
message: '<span>哈囉<span>'
}
})
</script>

指令 (Directives)

v-bind

透過指令 v-bind 的方式,將資料反應在HTML屬性上,更新 HTML 屬性。v-bind 是 Vue.js 裡面還蠻重要的功能,它可以
用來綁定DOM元素中的屬性,並且將屬性的值交由Vue.js來控管,因此我們便可以動態的去綁定、控制屬性,進而使得該元素變
成是可控制的元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
 <div id="app">
<img v-bind:src="imgSrc" v-bind:class="className" alt="">
</div>

<script>
var app = new Vue({
el: '#app',
data: {
imgSrc: 'https://images.unsplash.com/photo-1479568933336-ea01829af8de?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=d9926ef56492b20aea8508ed32ec6030&auto=format&fit=crop&w=2250&q=80',
className: 'img-fluid'
}
})
</script>

v-for

使用 v-for 來呈現資料,動態產生多筆資料在畫面上。 這個方法就類似用 forEach 將陣列(list) 的值一一取出放到變數 (item) 裡,也可以再加上索引值 (index)。
透過 v-for 的方式,我們可以將資料中的陣列遍歷出來,作法是在 v-for 後面的數值中,取一個任意的名稱(ex person)作為代表,取用方式如同一般我們要取出物件中的 value 一樣。
另外也可以透過第二個參數的部分(ex index)來取得該筆資料的實際索引值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<div id="app">
<pre>{{list}}</pre>
<ul>
<li v-for="(item,index) in list" >
{{index+1}}-{{item.name}}年齡是{{item.age}}
</li>
</ul>
</div>

<script>
var app = new Vue({
el: '#app',
data: {
list: [{
name: '小明',
age: 16
},
{
name: '媽媽',
age: 38,
}
]
}
})
</script>

v-for 在陣列和物件的迴圈的運用

使用 objectData 的時候,索引是物件的屬性

1
2
3
4
5
<ul>
<li v-for="(item, key) in objectData">
{{ key }} - {{ item.name }} {{ item.age }} 歲
</li>
</ul>
1
2
3
4
5
 <ul>
<li v-for="(item, key) in arrayData">
{{ key }} - {{ item.name }} {{ item.age }} 歲
</li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Vue.component('list-item', {
template: `
<li>
{{ item.name }} {{ item.age }} 歲
</li>
`,
props: ['item']
});

var app = new Vue({
el: '#app',
data: {
arrayData: [{
name: '小明',
age: 16
},
{
name: '漂亮阿姨',
age: 24
},
{
name: '杰倫',
age: 20
}
],
objectData: {
ming: {
name: '小明',
age: 16
},
auntie: {
name: '漂亮阿姨',
age: 24
},
jay: {
name: '杰倫',
age: 20
}
},
filterArray: [],
filterText: ''
}

v-for 與 key

Vue 在切換畫面的時候,是部份置換,所以下面反轉陣列的例子在切換 input 的時候,不會完整切換 DOM 元素,所以這裡使用 key 來改善這個問題

1
2
3
4
5
6
<ul>
<li v-for="(item, key) in arrayData" :key="item.age">
{{ key }} - {{ item.name }} {{ item.age }} 歲 <input type="text">
</li>
</ul>
<button class="btn btn-outline-primary" @click="reverseArray">反轉陣列</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Vue.component('list-item', {
template: `
<li>
{{ item.name }} {{ item.age }} 歲
</li>
`,props: ['item']
});

var app = new Vue({
el: '#app',
data: {
arrayData: [{
name: '小明',
age: 16
},
{
name: '漂亮阿姨',
age: 24
},
{
name: '杰倫',
age: 20
}
],
objectData: {
ming: {
name: '小明',
age: 16
},
auntie: {
name: '漂亮阿姨',
age: 24
},
jay: {
name: '杰倫',
age: 20
}
},
filterArray: [],
filterText: ''
},methods: {

reverseArray: function () {
this.arrayData.reverse()
console.log(this.arrayData)
},
}
})

v-for 與資料過濾

filterArry 一開始是一個空的陣列,現在新增一個 filterText,以輸入的文字,輸出後第一個出現的是我們輸入的資料、陣列迴圈內容,如果是 match 狀態就會回傳一個陣列(只要在 filter 裡是回傳 true,就會將 item push 回 filterArray)

1
2
3
4
5
6
7
8
 <input type="text" class="form-control" v-model="filterText" @keyup.enter="filterData">
<ul>
<li v-for="(item, key) in filterArray" :key="item.age">
{{ key }} - {{ item.name }} {{ item.age }} 歲 <input type="text">
</li>
</ul>

```

Vue.component(‘list-item’, {
template: <li> 歲 </li>,props: [‘item’]
});

 var app = new Vue({
   el: '#app',
   data: {
     arrayData: [{
         name: '小明',
         age: 16
       },
       {
         name: '漂亮阿姨',
         age: 24
       },
       {
         name: '杰倫',
         age: 20
       }
     ],
     objectData: {
       ming: {
         name: '小明',
         age: 16
       },
       auntie: {
         name: '漂亮阿姨',
         age: 24
       },
       jay: {
         name: '杰倫',
         age: 20
       }
     },
     filterArray: [],
     filterText: ''
   },

   methods: {
     filterData: function () {
       var vm = this; //指向的是vue應用程式的this,因此可以直接取用data
       vm.filterArray = vm.arrayData.filter(function (item) {

       console.log(vm.filterText, item.name, item.name.match(vm.filterText))
       });
       return item.name.match(vm.filterText);

     },
}
 })
1
2
3
4

### 一些特殊例子下運用 v-for 不被允許的狀況

- 直接修改陣列長度

<button class=”btn btn-outline-primary” @click=”cantWork”>無法運行

  • - 歲
1
2


Vue.component(‘list-item’, {
template: <li> 歲 </li>,props: [‘item’]
});

 var app = new Vue({
   el: '#app',
   data: {
     arrayData: [{
         name: '小明',
         age: 16
       },
       {
         name: '漂亮阿姨',
         age: 24
       },
       {
         name: '杰倫',
         age: 20
       }
     ],
     objectData: {
       ming: {
         name: '小明',
         age: 16
       },
       auntie: {
         name: '漂亮阿姨',
         age: 24
       },
       jay: {
         name: '杰倫',
         age: 20
       }
     },
     filterArray: [],
     filterText: ''
   },

   methods: {

    cantWork: function () {
       this.arrayData.length = 0;
       console.log(this.arrayData);


}
 })
1
2
3
4
5
6
7

//雖然陣列長度的「數字」被修改為 0,但畫面上的資料並沒有因此消失
![](https://i.imgur.com/6JBc8gt.png)

- 從陣列索引修改資料

要操作陣列的資料,不能直接透過索引方式

<button class=”btn btn-outline-primary” @click=”cantWork”>無法運行

  • - 歲
1
2


Vue.component(‘list-item’, {
template: <li> 歲 </li>,props: [‘item’]
});

 var app = new Vue({
   el: '#app',
   data: {
     arrayData: [{
         name: '小明',
         age: 16
       },
       {
         name: '漂亮阿姨',
         age: 24
       },
       {
         name: '杰倫',
         age: 20
       }
     ],
     objectData: {
       ming: {
         name: '小明',
         age: 16
       },
       auntie: {
         name: '漂亮阿姨',
         age: 24
       },
       jay: {
         name: '杰倫',
         age: 20
       }
     },
     filterArray: [],
     filterText: ''
   },

   methods: {

    cantWork: function () {
    this.arrayData[0]={
        name:'小強';
        age:'99',
    }
console.log(this.arrayData);
}}
   )
1
2
3
4
5
6
7
8
9
![](https://i.imgur.com/COHEbEU.png)

#### 解決方式:如果要操作的資料不在原有資料結構裡,用 Vue.set() 解決,寫進資料裡面讓它可重新被監控。

Vue.set( target, propertyName/index, value )
参数:
{Object | Array} target
{string | number} propertyName/index
{any} value

methods: {

Vue.set(this.arrayData, 0, {
name: ‘joy’,
age: 33
});
}

1
2

- 使用純數字迴圈
1
2
3
4

## v-if

透過v-if的情況,依據 v-if 後的條件是否為true時,決定該元素是否會顯示,若否則相反,並且該元素實際上會從DOM上消失。就是在 v-for 之上再加上一個判斷式。

          
  • NaN-年齡是
<script>
  var app = new Vue({
    el: '#app',
    data: {
      list: [{
          name: '小明',
          age: 16
        },
        {
          name: '媽媽',
          age: 38,
        }
      ]
    }
  })
</script>
1
2
3
4
5

### 使用 v-if、v-else 切換物件呈現

- 這裡的例子也是上面所說的判斷式運用,以`v-if` 運用原本已經定義在資料結構裡的 `isSuccess`
- 下方相鄰元素使用 `v-else` (代替 `isSuccess`)
<div class="alert alert-success" v-if="isSuccess">成功!</div>
<div class="alert alert-danger" v-else>失敗!</div>
<div class="form-check">
  <input type="checkbox" class="form-check-input" id="isSuccess" v-model="isSuccess">
  <label class="form-check-label" for="isSuccess">啟用元素狀態</label>
</div>
1
2


1
2
3
4

### v-else-if 製作分類頁籤

- 在 content 的元素上運用 `v-if` 和 `v-else-of` 判斷
1
2


1
2
3
4

### v-if 與 Key 的運用

由於 Vue 的部份置換特性,因此加上 key 值讓畫面完整切換
1
2


1
2
3
4

### v-if 與 v-show 差異

`v-show` 是透過移除 `display:none` 切換畫面的顯示
成功!
失敗!
1
2


1
2
3
4
5
6
7
8
9
10

![](https://i.imgur.com/SgciFh1.png)

而 v-if 則是直接移除 DOM 元素,一次只會顯示一個 DOM 元素

![](https://i.imgur.com/K2JfQ8N.png)

### v-for、v-if 的判斷式

v-for、v-if 一起寫在一個元素上的時候,會先執行 v-for 再執行 v-if
  • - 歲
1
2


Vue.component(‘list-item’, {
template: <li> 歲 </li>, props: [‘item’]
});

var app = new Vue({
  el: '#app',
  data: {
    arrayData: [{
        name: '小明',
        age: 16
      },
      {
        name: '漂亮阿姨',
        age: 24
      },
      {
        name: '杰倫',
        age: 20
      }
    ],
    objectData: {
      ming: {
        name: '小明',
        age: 16
      },
      auntie: {
        name: '漂亮阿姨',
        age: 24
      },
      jay: {
        name: '杰倫',
        age: 20
      }
    },
    filterArray: [],
    filterText: ''
  }
1
2
3
4

### v-for 與元件

現在建議元件使用 v-for 都加上 key。
1
2
3
4
5

## 處理使用者互動行為 v-on

v-on 可以綁定 method 名稱,當然也需要在實例中 methods 中宣告相同名稱的 function。v-on 顧名思義就是類似於原生 js 中的 on 事件,而使用方法一樣是要綁定的元素上,放一個 v-on 的屬性,例如,我們要在元素上定義一個點擊會 alert 一個提示的事件,我們就可以在後面寫上要觸發行為的條件(click),並且在 value 的值內放入指定的 method。
v-model 則是在 vue 中用來實現雙向綁定的方式。透過 v-model 綁定在元素上,我們可以創造一個雙向綁定資料的概念,也就是說假設我在表單組件 input 上設置 v-model 並綁定到 data 中的 meesage 上,他除了會即時顯示 data.message 中資料以外,我們在更動 input 中的數值時也會同步更改回 data 中 message 的 value。
1
2
3
4
5
6
7
8
9
10
11
12
13
14

### v-on 與 事件修飾符

v-on 也可透過修飾符操作事件,在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。
Vue 提供了事件修飾符,包括:

.stop
.prevent
.capture
.self
.once
.passive

- 此處在 v-on 之後透過修飾符取消預設行為
1
2
3
4

### v-on 與 按鍵修飾符

Vue 允許為 v-on 在監聽鍵盤事件時添加按鍵修飾符:
1
2
3
4

### 用縮寫表示按鍵修飾符

v-on 可以 `@` 符號來表示
1
2

v-bind 可以用 `:` 表示
1
2
3
4

### v-on 與帶入參數

如何透過參數將資料傳送到 method,直接在 button 元素上帶入參數,所以每次點擊就會在方法裡增加數字
  • 有 元
1
2


1
2


<style>
  .box {
    display: block;
    transition: all .5s;
  }

  .box.rotate {
    transform: rotate(45deg)
  }
</style>
1
2
3
4

## v-class 動態切換 className

可以傳給 v-bind:class 一個對象,動態切換 class:
<div class="alert alert-secondary">
  <ol class="mb-0">
    <li>為 .box 動態加上 className "rotate"</li>
  </ol>
</div>

<div id="app">
  <div class="box" :class="{'rotate':isTransform}"></div>
  <hr>
  <button class="btn btn-outline-primary" @click="isTransform=!isTransform">選轉物件</button>
</div>

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2020 CYC'S BLOG All Rights Reserved.

UV : | PV :