Vue2 第三天學習

龍恩0707發表於2017-05-03
個人小總結:1年多沒有寫部落格,感覺很多知識點生疏了,雖然工作上能解決問題,但是當別人問到某個知識點的時候,還是迷迷糊糊的,所以堅持寫部落格是硬道理的,因為大腦不可能把所有的知識點記住,有可能某一天忘了,但是我們工作上還是會使用,只是理論忘了,所以寫部落格的好處是可以把之前的東西重新看一遍後會在大腦裡面重新浮現起來,特別在面試的時候,別人問你的知識點的時候答不上來那種尷尬,但是平時經常使用到,只是說不出所以來的,因此寫部落格是最好的思路。

閱讀目錄

1.計算屬性

在模板內可以對一些屬性的計算。如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="app">  
      <p>正序:"{{ message }}"</p>
      <p>倒序:"{{ reversedMessage }}"</p>
    </div>  
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        message: 'Hello'
      },
      computed: {
        reversedMessage: function() {
          return this.message.split('').reverse().join('')
        }
      }
    })
  </script>
</html>

輸出結果為:

正序:"Hello"
倒序:"olleH"

如上我們提供的函式將用作屬性 vm.reversedMessage 的 getter 。如下程式碼:
console.log(vm.reversedMessage) // -> 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // -> 'eybdooG'

我們可以通過呼叫表示式中的 method 來達到同樣的效果:程式碼如下:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="app">  
      <p>Reversed message: "{{ reversedMessage() }}"</p>
    </div>  
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        message: 'Hello'
      },
      methods: {
        reversedMessage: function () {
          return this.message.split('').reverse().join('')
        }
      }
    });
    console.log(vm.reversedMessage()) // -> 'olleH'
  </script>
</html>

那麼他們的區別是?
計算屬性是基於他們的依賴進行快取的。計算屬性只有在它的相關依賴發生改變時才會重新求值。也就是說只要message值沒有發生變化,多次訪問reversedMessage計算屬性會立即返回之前的結果,不必再執行函式。
但是method方法只要發生重新渲染,總是會執行該函式。

2.Class 與 Style的繫結。

1. 繫結Html class --- 物件語法
我們可以傳給 v-bind:class 一個物件,以動態的切換class。如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="app">  
      <div class="static" v-bind:class = "{ active: isActive, 'text-danger': hasError }"></div>
    </div>  
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        isActive: true,
        hasError: true
      }
    });
  </script>
</html>

程式碼被渲染為如下:

<div id="app"><div class="static active text-danger"></div></div>

當 isActive 或者 hasError 變化時,class 列表將相應地更新。例如,如果 hasError 的值為 false , class列表將變為 "static active "。
也可以直接繫結資料裡的一個物件:如下程式碼

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="app">  
      <div class="static" v-bind:class="classObject"></div>
    </div>  
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        classObject: {
          active: true,
          'text-danger': true
        }
      }
    });
  </script>
</html>

渲染效果和上面一樣。
也可以在這裡繫結返回物件的計算屬性。如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="app">  
      <div class="static" v-bind:class="classObject"></div>
    </div>  
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        isActive: true,
        error: null
      },
      computed: {
        classObject: function () {
          return {
            active: this.isActive && !this.error,
            'text-danger': this.error && this.error.type === 'fatal',
          }
        }
      }
    });
  </script>
</html>

渲染後的程式碼如下:

<div id="app"><div class="static active"></div></div>

2. 陣列語法
我們可以把一個陣列傳給 v-bind:class ,以應用一個 class 列表:如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="app">  
      <div class="static" v-bind:class="[activeClass, errorClass]"></div>
    </div>  
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        activeClass: 'active',
        errorClass: 'text-danger'
      }
    });
  </script>
</html>

被渲染為如下程式碼:

<div id="app"><div class="static active text-danger"></div></div>

3. 使用在元件上
例如,如果你宣告瞭這個元件:

Vue.component('my-component', {
  template: '<p class="foo bar">Hi</p>'
})
var vm = new Vue({
  el: '#app'
});

使用元件的時候 新增一些class,如下程式碼:

<div id="app">  
  <my-component class='baz boo'></my-component>
</div>

所有程式碼如下:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="app">  
      <my-component class='baz boo'></my-component>
    </div>  
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">

    Vue.component('my-component', {
      template: '<p class="foo bar">Hi</p>'
    })
    var vm = new Vue({
      el: '#app'
    });
  </script>
</html>

HTML最終被渲染為:

<div id="app"><p class="foo bar baz boo">Hi</p></div>

同樣的適用於繫結 HTML class :

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="app">  
      <my-component v-bind:class="{ active: isActive }"></my-component>
    </div>  
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">

    Vue.component('my-component', {
      template: '<p class="foo bar">Hi</p>'
    })
    var vm = new Vue({
      el: '#app',
      data: {
        isActive: true
      }
    });
  </script>
</html>

當isActive為true的時候,HTML最終被渲染成為如下程式碼:

<div id="app"><p class="foo bar active">Hi</p></div>

4. 級聯內聯樣式
如下級聯樣式程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="app">  
      <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">11112222</div>
    </div>  
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">

    Vue.component('my-component', {
      template: '<p class="foo bar">Hi</p>'
    })
    var vm = new Vue({
      el: '#app',
      data: {
        activeColor: 'red',
        fontSize: 30
      }
    });
  </script>
</html>

頁面被渲染為如下程式碼:

<div id="app"><div style="color: red; font-size: 30px;">11112222</div></div>

也可以繫結到一個樣式物件通常更好,讓模板更清晰:如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="app">  
      <div v-bind:style="styleObject">11112222</div>
    </div>  
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">

    Vue.component('my-component', {
      template: '<p class="foo bar">Hi</p>'
    })
    var vm = new Vue({
      el: '#app',
      data: {
        styleObject: {
          color: 'red',
          fontSize: '22px'
        }
      }
    });
  </script>
</html>

程式碼被渲染成為如下:

<div id="app"><div style="color: red; font-size: 22px;">11112222</div></div>

3.列表渲染

3-1 v-for
我們用 v-for 指令根據一組陣列的選項列表進行渲染。 v-for 指令需要以 item in items 形式的特殊語法, items 是源資料陣列並且 item 是陣列元素迭代的別名。
如下面程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <ul id='app'>
      <li v-for="item in items">
        {{ item.message }}
      </li>
    </ul> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        items: [
          {message: 'foo'},
          {message: 'bar'}
        ]
      }
    });
  </script>
</html>

頁面程式碼被渲染為如下:

<ul id="app"><li>foo</li><li>bar</li></ul>

v-for 我們擁有對父作用域屬性的完全訪問許可權 還支援一個可選的第二個引數為當前項的索引。
如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <ul id='app'>
      <li v-for="(item, index) in items">
        {{ parentMessage }} - {{ index }} - {{ item.message }}
      </li>
    </ul> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        parentMessage: 'Parent',
        items: [
          {message: 'foo'},
          {message: 'bar'}
        ]
      }
    });
  </script>
</html>

頁面被渲染為如下程式碼:

<ul id="app">
  <li>Parent - 0 - foo</li>
  <li>Parent - 1 - bar</li>
</ul>

可以用 of 替代 in 作為分隔符。
<div v-for="item of items"></div>
3-2 在template中也可以使用 v-for , 如下程式碼:

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider"></li>
  </template>
</ul>

3-3 物件迭代v-for
我們也可以用 v-for 通過一個物件的屬性來迭代。

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <ul id='app'>
      <li v-for="value in object">
        {{ value }}
      </li>
    </ul> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        object: {
          f: 'kongzhi',
          l: 'longen',
          Age: 30
        }
      }
    });
  </script>
</html>

程式碼被渲染為:

<ul id="app">
  <li>kongzhi</li>
  <li>longen</li>
  <li>30</li>
</ul>

可以提供第二個的引數為鍵名:如下程式碼:

<div v-for="(value, key) in object">
{{ key }} : {{ value }}
</div>

第三個引數為索引:

<div v-for="(value, key, index) in object">
{{ index }}. {{ key }} : {{ value }}
</div>

3-4 整數的迭代
v-for 也可以取整數。如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <span v-for="n in 10">{{ n }}</span>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app'
    });
  </script>
</html>

頁面程式碼被渲染為:

<div id="app">
  <span>1</span>
  <span>2</span>
  <span>3</span>
  <span>4</span>
  <span>5</span>
  <span>6</span>
  <span>7</span>
  <span>8</span>
  <span>9</span>
  <span>10</span>
</div>

3-5 元件使用v-for
元件有自己獨立的作用域。為了傳遞迭代資料到元件裡,我們要用 props. 如下程式碼:

<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index">
</my-component>

下面是一個demo;頁面上預設有3項列表資料,當使用者在輸入框輸入值的時候 按enter鍵的時候 會增加一項,當然也可以點選刪除x刪除一項。

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <input 
        v-model='newTodoText'
        v-on:keyup.enter='addNewTodo'
        placeholder="Add a todo" 
      >
      <ul>
        <li 
          is='todo-item'
          v-for="(todo, index) in todos"
          v-bind:title='todo'
          v-on:remove="todos.splice(index, 1)"
        ></li>
      </ul>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    Vue.component('todo-item', {
      template: '<li>{{ title }}<button v-on:click="$emit(\'remove\')">X</button></li>',
      props: ['title']
    })
    new Vue({
      el: '#app',
      data: {
        newTodoText: '',
        todos: [
          'do the dishes',
          'Take out the trash',
          'Mow the lawn'
        ]
      },
      methods: {
        addNewTodo: function() {
          this.todos.push(this.newTodoText);
          this.newTodoText = '';
        }
      }
    });
  </script>
</html>

檢視效果

4.事件處理器

 4-1 v-on 監聽事件 程式碼如下:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <button v-on:click="counter += 1">增加1</button>
      <p>這個按鈕被點選了 {{ counter }}次。</p>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      data: {
        counter: 0
      }
    })
  </script>
</html>

檢視效果

4-2 方法事件處理器
直接把 JavaScript 程式碼寫在 v-on 指令中是不可行的,比如當程式碼變得很複雜的時候,因此 v-on 可以接收一個定義的方法來呼叫。

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <button v-on:click="greet">Greet</button>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      data: {
        name: 'vue'
      },
      methods: {
        greet: function(event) {
          alert('hello ' + this.name + '!'); // hello vue
          // event 是原生的 DOM事件
          alert(event.target.tagName); // BUTTON
        }
      }
    })
  </script>
</html>

檢視效果

也可以用 JavaScript 直接呼叫方法
example1.greet() // -> 'Hello Vue'

4-3 內聯處理器方法
除了直接繫結到一個方法,也可以用內聯 JavaScript 語句:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <button v-on:click="say(1)">1</button>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      methods: {
        say: function(message) {
          alert(message);
        }
      }
    });
  </script>
</html>

檢視效果

有時也需要在內聯語句處理器中訪問原生 DOM 事件。可以用特殊變數 $event 把它傳入方法:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <button v-on:click="warn('warn message', $event)">submit</button>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      methods: {
        warn: function(message, event) {
          console.log(event); // 開啟控制檯檢視 列印出原生事件的所有資訊
          alert(message);
        }
      }
    });
  </script>
</html>

檢視效果

4-4 事件修飾符
在事件處理程式中呼叫 event.preventDefault() 或 event.stopPropagation()。儘管我們可以在 methods 中輕鬆實現這點。
Vue.js 為 v-on 提供了 事件修飾符。通過由點(.)表示的指令字尾來呼叫修飾符。
.stop
.prevent
.capture
.self
.once

<!-- 阻止點選事件冒泡 -->
<a v-on:click.stop='dothis'></a>

<!-- 提交事件不再過載頁面 -->
<form v-on:submit.prevent='onSubmit'></form>

<!-- 修飾符可以連著寫 -->
<a v-on:click.stop.prevent='dothis'></a>

<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>

<!-- 新增事件偵聽器時使用事件捕獲模式 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只當事件在該元素本身(而不是子元素)觸發時觸發回撥 -->
<div v-on:click.self="doThat">...</div>

<!-- 點選事件將只會觸發一次 (2.14 新增)-->
<a v-on:click.once="doThis"></a>

4-5 按鍵修飾符
在監聽鍵盤事件時,我們經常需要監測常見的鍵值。 Vue 允許為 v-on 在監聽鍵盤事件時新增按鍵修飾符:

<!-- 只有在 keyCode 是 13 時呼叫 vm.submit() -->
<input v-on:keyup.13="submit">
// Vue 為最常用的按鍵提供了別名:
 <!-- 同上 -->
<input v-on:keyup.enter="submit">
<!-- 縮寫語法 -->
<input @keyup.enter="submit">
// 全部的按鍵別名:
.enter
.tab
.delete (捕獲 “刪除” 和 “退格” 鍵)
.esc
.space
.up
.down
.left
.right

5.表單控制元件繫結 

v-model 負責監聽使用者的輸入事件以更新資料。
5-1 input框如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <input v-model="message" placeholder="edit me" />
      <p>Message is: {{ message }}</p>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      data: {
        message: ''
      }
    });
  </script>
</html>

檢視效果

5-2 多行文字 textrea

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <span>message is: </span>
      <p>{{ message }}</p>
      <br />
      <textarea v-model="message" placeholder="add multiple lines" style="height: 100px"></textarea>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      data: {
        message: ''
      }
    });
  </script>
</html>

檢視效果

5-3 核取方塊-- 單個勾選框 邏輯值

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <input type="checkbox" v-model='checked' />
      <label>{{ checked }}</label>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      data: {
        checked: false
      }
    });
  </script>
</html>

檢視效果

核取方塊-- 多個勾選框,繫結到同一個陣列

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <input type="checkbox" value="Jack" v-model="checkedNames">
      <label>Jack</label>
      <input type="checkbox" value="John" v-model="checkedNames">
      <label>John</label>
      <input type="checkbox" value="Mike" v-model="checkedNames">
      <label>Mike</label>
      <br>
      <span>Checked names: {{ checkedNames }}</span>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      data: {
        checkedNames: []
      }
    });
  </script>
</html>

檢視效果

單選按鈕

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <input type="radio" value="One" v-model="picked">
      <label>One</label>
      <br>
      <input type="radio" value="Two" v-model="picked">
      <label>Two</label>
      <br>
      <span>Picked: {{ picked }}</span>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      data: {
        picked: ''
      }
    });
  </script>
</html>

檢視效果

選擇列表 -- 單選列表

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <select v-model="selected">
        <option>A</option>
        <option>B</option>
        <option>C</option>
      </select>
      <span>Selected: {{ selected }}</span>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      data: {
        selected: 'A'
      }
    });
  </script>
</html>

檢視效果

多選列表(繫結到一個陣列):

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <select v-model="selected" multiple style="width: 50px">
        <option>A</option>
        <option>B</option>
        <option>C</option>
      </select>
      <br>
      <span>Selected: {{ selected }}</span>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      data: {
        selected: []
      }
    });
  </script>
</html>

檢視效果

動態選項,用 v-for 渲染:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id='app'>
      <select v-model="selected">
        <option v-for="option in options" v-bind:value="option.value">
          {{ option.text }}
        </option>
      </select>
      <span>Selected: {{ selected }}</span>
    </div> 
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    var example1 = new Vue({
      el: '#app',
      data: {
        selected: 'A',
        options: [
          { text: 'one', value: 'A' },
          { text: 'two', value: 'B' },
          { text: 'three', value: 'C' },
        ]
      }
    });
  </script>
</html>

檢視效果

如果想自動將使用者的輸入值轉為 Number 型別(如果原值的轉換結果為 NaN 則返回原值),可以新增一個修飾符 number 給 v-model 來處理輸入值

<input v-model.number="age" type="number">

如果要自動過濾使用者輸入的首尾空格,可以新增 trim 修飾符到 v-model 上過濾輸入:

<input v-model.trim="msg">

相關文章