1. 程式人生 > >後端開發者的Vue學習之路(二)

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

right alt method 標簽 .com arr rac tde iyu

目錄

  • 上篇內容回顧:
  • 數據綁定
    • 表單輸入框綁定
      • 單行文本輸入框
      • 多行文本輸入框
      • 復選框checkbox
      • 單選框radio
      • 選擇框select
    • 數據綁定的修飾符
      • .lazy
      • .number
      • .trim
  • 樣式綁定
    • class綁定
      • 對象語法:
      • 數組語法:
    • style綁定
      • 對象語法:
      • 數組語法:
    • 補充:
  • 事件
    • 綁定事件
    • 事件修飾符
    • 按鍵修飾符
    • 事件綁定的簡寫
    • 補充:
  • Vue指令
  • 數組操作
    • 官網的話
    • 補充:
  • Vue的元素復用問題
    • 數據殘留問題
      • 問題的解決:

首發日期:2019-01-20


上篇內容回顧:

上篇內容講了

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

數據綁定


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

技術分享圖片


表單輸入框有value這個值,在表單輸入框裏使用v-model會把表單輸入框與實例的數據進行“智能”綁定(為什麽說智能,因為有些輸入框的數據是value屬性,有些不是)。


表單輸入框綁定

你可以用 v-model 指令在表單 <input><textarea>

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

v-model 會忽略所有表單元素的 value、checked、selected 特性的初始值而總是將 Vue 實例的數據作為數據來源。如果希望輸入框有初始值,你應該在組件的 data 選項中聲明初始值。


單行文本輸入框

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

    <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 識別節點的一個通用機制。



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