後端開發者的Vue學習之路(二)

首發日期:2019-01-20前端


上篇內容回顧:

上篇內容講了vue

  • Vue的介紹:優勢,MVVM
  • Vue的靜態導入與安裝,以及hello world
  • 實例可定義的內容:el,data,methods,生命週期鉤子(包括計算屬性,偵聽器也是能夠定義在實例中的)
  • 計算屬性
  • 偵聽器

數據綁定


v-model能夠把某個實例的數據與元素的數據綁定。這樣當其中一份數據發生變化時,與之綁定的數據也會發生變化。好比:把示例中的數據(在頁面中用{{}}顯示出來)與輸入框的數據綁定npm


表單輸入框有value這個值,在表單輸入框裏使用v-model會把表單輸入框與實例的數據進行「智能」綁定(爲何說智能,由於有些輸入框的數據是value屬性,有些不是)。數組


表單輸入框綁定

你能夠用 v-model 指令在表單 <input><textarea><select> 元素上建立雙向數據綁定。它會根據控件類型自動選取正確的方法來更新元素。儘管有些神奇,但 v-model 本質上不過是語法糖。它負責監聽用戶的輸入事件以更新數據,並對一些極端場景進行一些特殊處理。瀏覽器

v-model 會忽略全部表單元素的 value、checked、selected 特性的初始值而老是將 Vue 實例的數據做爲數據來源。若是但願輸入框有初始值,你應該在組件的 data 選項中聲明初始值。app


單行文本輸入框

會把單行文本輸入框的value綁定到實例的數據中,由於value的數據就是單行文本輸入框的數據。dom

<body>
      <div id="vm">
        <input v-model="message" placeholder="edit me">
        <p>Message is: {{ message }}</p>
        <input type="text" v-bind:value="message">
        <!-- 不能使用普通的value=message,否則會識別不成正確的message,因此第三行用了v-bind -->
      </div>
    </body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var vm = new Vue({
              el: '#vm',
              data:{
                message:"hello world!"
              }
        })
    </script>


多行文本輸入框

會把多行文本元素內的文本綁定到實例的數據中,由於多行文本元素內的文本就是單行文本輸入框的數據。函數

<body>
  <div id="vm">
    <span>Multiline message is:</span>
    <p style="white-space: pre-line;">{{ message }}</p>
    <br>
    <textarea v-model="message" placeholder="add multiple lines"></textarea>
  </div>
</body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#vm',
      data:{
        message:"hello world!"
      }
})
</script>

在文本區域<textarea></textarea>使用插值表達式{{}}來插值並不會生效,應該用 v-model 來代替。性能


複選框checkbox

單個複選框:複選框也有value,不給定value值的時候value默認是布爾值(被勾選是true,沒有勾選是false)

<body>
  <div id="vm">
    <input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{ checked }}</label>
  </div>
</body>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#vm',
      data:{
        checked:false
      }
})
</script>


多個複選框:指定了value以後,實例綁定的數據是對應的value值【因爲是多個複選框綁定到同一個實例上,因此這個實例數據應該是數組類型的。】

<body>
  <div id='example-3'>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</div>
</body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#example-3',
      data:{
        checkedNames:[] // 值爲多個input的value的數組
      }
})
</script>


單選框radio

radio也有value,因此與實例綁定的數據就是value的值

<body>
  <div id="example-4">
    <input type="radio" id="one" value="One" v-model="picked">
    <label for="one">One</label>
    <br>
    <input type="radio" id="two" value="Two" v-model="picked">
    <label for="two">Two</label>
    <br>
    <span>Picked: {{ picked }}</span>
  </div>
</body>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    var vm = new Vue({
  el: '#example-4',
  data: {
    picked: ''// picked的值爲input的value值
  }
})
</script>


選擇框select

select的值來源與子標籤option。當select 的option沒有value值的時候,默認綁定的數據爲option元素的文本值;當有value時,默認綁定的數據爲option元素的value值。

<body>
      <div id="example-5">
        <select v-model="selected">
          <option disabled value="">請選擇</option>
          <option value ='a'>A</option> <!-- 這個用來測試有value的狀況-->
          <option>B</option>
          <option>C</option>
        </select>
        <span>Selected: {{ selected }}</span>
      </div>
    </body>
      <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
      <script>
        var vm = new Vue({
      el: '#example-5',
      data: {
        selected: "" // selected 的值爲 a/B/C
      }
    })
    </script>


select框容許多選時:那麼這時候實例的數據應該是一個數組,數組元素是option的文本值(無value時)或value

<body>
  <div id="example-5">
    <select multiple style="width: 50px;" v-model="selected">
      <option disabled value="">請選擇</option>
      <option value='a'>A</option>
      <option>B</option>
      <option>C</option>
    </select>
    <span>Selected: {{ selected }}</span>
  </div>
</body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    var vm = new Vue({
  el: '#example-5',
  data: {
    selected: [] // 全選時: [ "a", "B", "C" ]
  }
})
</script>


數據綁定的修飾符

.lazy

在默認狀況下,v-model 在每次 input 事件觸發後將輸入框的值與數據進行同步 (除了輸入法組合文字時,這時候數據還沒徹底輸入到輸入框中)。
你能夠添加 lazy 修飾符,從而轉變爲使用 change 事件進行同步:

<!-- 在「change」時而非「input」時更新 -->
<input v-model.lazy="msg" >


.number

若是想自動將用戶的輸入值轉爲數值類型,能夠給 v-model 添加 number 修飾符:

<input v-model.number="age" type="number">
這一般頗有用,由於即便在 type="number" 時,HTML 輸入元素的值也總會返回字符串。若是這個值沒法被 parseFloat() 解析,則會返回原始的值。


.trim

若是要自動過濾用戶輸入的首尾空白字符,能夠給 v-model 添加 trim 修飾符:

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



樣式綁定


咱們平時也可使用class='xxx'或style='xxx:xxxx'來綁定樣式。爲何要選擇轉去使用Vue的樣式綁定?由於在Vue中class或style也能夠定義成數據,你可能會想要「發生XXX狀況後,某元素變成某樣式」,這個時候你須要定義「行爲」來切換樣式了,而這時候若是你使用Vue本身的樣式切換會比較方便(由於首先你要獲取某個元素的class屬性,而後再從新賦值,這個操做可能須要本身定義一些dom操做)。


class綁定

使用v-bind:class來進行class綁定


對象語法:

格式一:傳入的數據格式是{ class名: 布爾數據,.... },布爾數據影響class是否出如今元素的class屬性中。

<div id="app">
            <div v-bind:class="{ active: isActive }">haha</div>
        </div>
        <!--
       var app = new Vue({
                    el: '#app',
                    data: {
                        isActive: true  // 影響着active這個class是否出現
                    },
                })
         -->
         <!--
            <style>
                .active {
                    color: red;
                }
            </style>
          -->

格式一:傳入的數據格式是對象名,對象的數據格式是{ class名: 布爾數據,.... },布爾值影響class是否出如今元素的class屬性中。

<div id="app">
            <div v-bind:class="classObject">haha</div>
        </div>
        <!--
       var app = new Vue({
                    el: '#app',
                    data: {
                        classObject: {
                            active: true
                        }
                    },
                })
         -->
         <!--
            <style>
                .active {
                    color: red;
                }
            </style>
          -->


數組語法:

格式一:

<div id="app">
            <div v-bind:class="[activeClass]">haha</div>
        </div>
        <!--
       var app = new Vue({
                    el: '#app',
                    data: {
                        activeClass:'active'
                    },
                })
         -->
         <!--
            <style>
                .active {
                    color: red;
                }
            </style>
          -->

style綁定

使用v-bind:style來進行style綁定

對象語法:

格式一:傳入的數據格式是{ 樣式名: 實例數據名(樣式值), .... }

<div id="app">
            <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">haha</div>
        </div>
        <!--
       var app = new Vue({
                    el: '#app',
                    data: {
                        activeColor:'red',
                        fontSize: 14
                    },
                })
         -->

格式二:傳入的數據是一個對象,對象的數據格式是{ 樣式名: 樣式值, .... }

<div id="app">
            <div v-bind:style="styleObject">haha</div>
        </div>
        <!--
       var app = new Vue({
                    el: '#app',
                    data: {
                        styleObject: {
                            color:'red',
                            fontSize: "14px"
                        }
                    },
                })
         -->


數組語法:

傳入的數據是一個數組,數組的元素是多個對象,對象的數據格式是{ 樣式名: 樣式值, .... }

<div id="app">
            <div v-bind:style="[styleObject]">haha</div>
        </div>
        <!--
       var app = new Vue({
                    el: '#app',
                    data: {
                        styleObject: {
                            color:'red',
                            fontSize: "14px"
                        }
                    },
                })
         -->

補充:

  • 當 v-bind:style 使用須要添加瀏覽器引擎前綴的 CSS 屬性時,如 transform,Vue.js 會自動偵測並添加相應的前綴。



事件

綁定事件

可使用v-on:事件類型='函數名'來綁定事件。

<div id="app">
            <button v-on:click="myclick">點擊事件</button>
            <!-- on:後面跟事件類型 -->
        </div>
        <!-- 
               var app = new Vue({
                  el: '#app',
                  methods: { // 注意:是在methods裏面定義函數
                    myclick:function (){
                        alert("message")
                    }
                  }
                })
        -->


事件修飾符

事件修飾符能夠影響事件的運行,事件修飾符使用.跟在事件類型的後面,例如:<a v-on:click.stop="doThis"></a>

  • .prevent 修飾符告訴 v-on 指令對於觸發的事件,調用 event.preventDefault()來阻止默認的元素行爲,例如默認點擊a元素時會進行頁面跳轉,若是咱們給事件加了prevent修飾符,那麼對應的a元素就不會進行網頁跳轉了v-on:click.prevent='myFunction'
  • .stop 修飾符告訴v-on 指令對於觸發的事件,阻止這個事件的冒泡(冒泡表明這個觸發的事件也會傳遞給父元素這些祖宗元素)
  • .once修飾符告訴v-on 指令對於觸發的事件只會觸發一次。
  • 還有好幾個事件修飾符,有興趣的能夠自查。這個仍是相對少用的。


<body>
      <div id="app">
        <a v-on:click.prevent='myFunction' href='#'>aaa</a>
        <!-- 默認狀況下,點擊a元素會進行跳轉,
          上面用#來演示,若是url多了一個#說明a的原生事件觸發了,
        而咱們如今用prevent來阻止了a元素原始的事件
        -->
      </div>
    </body>
      <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
      <script>
        var vm = new Vue({
          el: '#app',
          methods: {
            myFunction: function () {
              alert('haha')
            }
          }
        })
    </script>


按鍵修飾符

你可能須要監聽鍵盤來觸發事件,好比最經常使用的就是監聽enter鍵了。
按鍵修飾符也使用.跟在事件類型的後面 ,例如:<input v-on:keyup.enter="submit">

  • .enter表明enter鍵修飾符
  • .up .down .left .right表明四個方向鍵的修飾符。
  • 【上面給出了常見的「按鍵修飾符別名」,是別名,真實的值多是一個數字】
  • 【這裏對於按鍵修飾符就不說那麼多了,須要用再查吧。】


事件綁定的簡寫

<!-- 完整語法 -->
<a v-on:click="doSomething">...</a>

<!-- 縮寫 -->
<a @click="doSomething">...</a>


補充:

  • 還能夠自定義事件【不過目前我作的一些前端項目好像都沒怎麼涉及,有興趣的能夠自查】



Vue指令

Vue的指令是以v-開頭的,它們各有各的左右,在前面已經介紹了很多了。如今再彙總一下。


  • v-text:向元素中輸出文本
  • v-html:向元素中輸入html文本
  • v-if:根據條件來判斷是否渲染元素(同類的v-else,v-else-if)
  • v-show:根據條件來判斷是否顯示元素
  • v-for:循環渲染元素
  • v-bind:爲元素綁定屬性
  • v-model:進行數據的雙向綁定
  • v-on: 爲元素綁定事件
  • v-once用來聲明元素只渲染一次。



數組操做


爲何要特地地說一下數組的操做呢?由於數組是很是經常使用的數據類型,而在Vue中有些數組操做並不會觸發視圖更新。爲了確保數據是「響應式」的,因此特地講一下這個。


下面的代碼演示了使用普通數組操做方法時「響應失敗」的狀況:

<body>
      <div id="app">
        <p>{{ myArray}}</p>
        <button @click='addValue1'>下標法添加</button>
        <button @click='addValue2'>push法</button>
        <!-- 若是你點了第一個,再點第二個,第一個的添加會在第二個的時候再成功顯示 -->
      </div>
    </body>
      <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
      <script>
        var vm = new Vue({
          el: '#app',
          data: {
            myArray: [1,2,3]
          },
          methods: {
            addValue1: function(){
              this.myArray[1]=333
            },
            addValue2: function(){
              this.myArray.push('999999')
            }
          }
        })
    </script>


下面這些對數組操做的方法將會觸發視圖更新。

  • push():向數組末尾添加元素
  • pop():從數組末尾取出一個元素
  • shift():數組的第一個元素從其中刪除,並返回第一個元素的值
  • unshift():向數組的開頭添加一個或更多元素,並返回新的長度
  • splice():從數組中添加/刪除項目,而後返回被刪除的項目
  • sort():對數組的元素進行排序
  • reverse():對數組的元素進行逆序排序


官網的話

【官網的話】因爲 JavaScript 的限制,Vue 不能檢測如下變更的數組:

  1. 當你利用索引直接設置一個項時,例如:vm.items[indexOfItem] = newValue
  2. 當你修改數組的長度時,例如:vm.items.length = newLength

爲了解決第一類問題,如下兩種方式均可以實現和 vm.items[indexOfItem] = newValue 相同的效果,同時也將觸發狀態更新:

Vue.set(vm.items, indexOfItem, newValue)vm.items.splice(indexOfItem, 1, newValue)vm.$set(vm.items, indexOfItem, newValue)
爲了解決第二類問題,你可使用 splice:vm.items.splice(newLength)


補充:

  • 仍是因爲 JavaScript 的限制,Vue 不能檢測對象屬性的添加或刪除:
var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 如今修改a是響應式的

vm.b = 2
// `vm.b` 不是響應式的


  • 有時,咱們想要顯示一個數組的過濾或排序副本,而不實際改變或重置原始數據(不改變原來的數據,表明建立一個副本,而sort會影響源數組,因此咱們須要新的數組來存儲)。在這種狀況下,能夠建立返回過濾或排序數組的計算屬性。【若是你處理數組有多種狀況,你可使用一個 method 方法,用傳參來定義如何處理數組
<body>
      <div id="app">
        <p>{{ numbers }}</p>
        <ul >
          <li v-for="n in evenNumbers">{{ n }}</li>
        </ul>
      </div>
      
    </body>
      <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
      <script>
        var vm = new Vue({
          el: '#app',
          data: {
            numbers: [ 1, 2, 3, 4, 5 ]
          },
          computed: {
            evenNumbers: function () {
              return this.numbers.filter(function (number) {
                return number % 2 === 0
              })
            }
          }
        })
    </script>



Vue的元素複用問題

Vue 會盡量高效地渲染元素,一般會複用已有元素而不是從頭開始渲染。這麼作除了使 Vue 變得很是快以外,還有其它一些好處。

數據殘留問題

而由於複用問題,因此可能會致使如下問題。因爲輸入框被複用,因此輸入框的數據殘留了下來。


<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address">
</template>


問題的解決:

Vue 爲你提供了一種方式來表達「這兩個元素是徹底獨立的,不要複用它們」。只需添加一個具備惟一值的 key 屬性便可(沒有key的label仍然被複用了):

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>


當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它默認用「就地複用」策略。若是數據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數據項的順序, 而是簡單複用此處每一個元素,而且確保它在特定索引下顯示已被渲染過的每一個元素。
這個默認的模式是高效的,可是隻適用於不依賴子組件狀態或臨時 DOM 狀態 (例如:表單輸入值) 的列表渲染輸出。
爲了給 Vue 一個提示,以便它能跟蹤每一個節點的身份,從而重用和從新排序現有元素,你須要爲每項提供一個惟一 key 屬性。理想的 key 值是每項都有的惟一 id。這個特殊的屬性至關於 Vue 1.x 的 track-by ,但它的工做方式相似於一個屬性,因此你須要用 v-bind 來綁定動態值 (在這裏使用簡寫):

<div v-for="item in items" :key="item.id">
  <!-- 內容 -->
</div>


建議儘量在使用 v-for 時提供 key,除非遍歷輸出的 DOM 內容很是簡單,或者是刻意依賴默認行爲以獲取性能上的提高,由於它是 Vue 識別節點的一個通用機制。

相關文章
相關標籤/搜索