從 Vue 1.x 遷移


目錄

  • #FAQ

  • 範本

    • 生命週期鉤子函數

    • beforeCompile

    • #attached
    • #detached
    • init
  • ready

    • v-for
    • v-for 遍歷陣列時的參數順序
    • #v-for 遍歷物件時的參數順序
    • $index and $key
    • #track-by
  • #v-for 範圍值

    • #Props
    • coerce Prop 的參數
    • #twoWay Prop 的參數
    • v-bind 的.once和.sync 修飾符
    • #修改Props
  • ##根實例的Props

    • #計算屬性

  • cache: false

    • #Built-In 指令

    • v-bind 真/假值

    • 用v-on 監聽原生事件

    • 帶有debounce 的v-model

    • 使用lazy 或number 參數的v-model

    • 使用內聯value的v-model

    • v-model with v-for Iterated Primitive Values

    • #帶有!important 的v-bind:style

      ################v-el 和v-ref####################################################################
    • v-show後面使用v-else

  • #自訂指令

  • 過渡

  • 過渡的stagger 參數

    • ##events 選項

    • Vue.directive('on').keyCodes

    • #$dispatch 和$broadcast

  • #過濾器

      ##插入文字以外的篩選器
    • 篩選器參數符號
    • 內建文字過濾器
  • 雙向過濾器

    • ##插槽
  • 已重名的插槽

  • 計算插值
  • # 圍繞DOM 的實例方法

    • vm.$after
    • #vm.$remove
    • ##底層實例方法

    #vm.$eval
  • vm.$interpolate
    • vm.$log
  • 實例DOM 選項
    • replace: false
    • ##全域設定
    • Vue.config.debug
    • Vue.config.async
  • Vue.config.delimiters

    • Vue.config.unsafeDelimiters

    • #全域API
    • #帶el 的Vue.extend


Vue.elementDirective

Vue.partial

FAQ

#哇,非常長的一頁!是否意味著 Vue 2.0 已經完全不同了呢,是否需要從頭學起呢,Vue 1.0 的專案是不是沒法遷移了? ############很開心地告訴你,不是!幾乎 90% 的 API 和核心概念都沒變。因為本節包含了許多詳盡的闡述以及許多遷移的例子,所以顯得有點長。不用擔心,###你不必從頭到尾把本節讀一遍! ############我該從哪裡開始專案遷移呢? ######### 1. 首先,在目前專案下執行###遷移工具###。我們非常謹慎地把高階 Vue 升級流程簡化為使用簡單的命令列工具。當工具識別出舊有的特性後,就會告知你並給予建議,同時附上關於詳細資訊的連結。 ###

 2. 然後,瀏覽本頁面的側邊欄所列的內容。如果發現有的標題對你的專案有影響,但是遷移工具沒有給予提示,請檢查自己的專案。

 3. 如果你的專案有測試程式碼,運行並查看仍然失敗的地方。如果沒有測試程式碼,在瀏覽器中打開你的程序,透過導航環顧並留意那些報錯或警告訊息。

 4. 現在,你的應用程式應該已徹底完成遷移。如果你渴望了解更多,可以閱讀本頁面剩餘部分 - 或從介紹部分,從頭開始深入新的文件和改進過的指南。由於你已經熟悉一些核心概念,所以許多部分已經被刪除。

將 Vue 1.x 版本的應用程式移轉到 2.0 則要花多久時間?

這取決於幾個因素:

  • 取決於你應用程式的規模(中小型的基本上一天內就​​可以搞定) 。

  • 取決於你分心和開始 2.0 最酷的新功能的次數。 無法判斷時間,我們建構 2.0 應用程式的時候也常發生這種事!

  • 取決於你使用了哪些舊有的特性。大部分可以透過尋找和取代 (find-and-replace) 來實現升級,但有一些可能還是要花點時間。如果你沒有遵循最佳實踐,Vue 2.0 會盡力強迫你去遵循。這有利於專案的長期運行,但也可能意味著重大重構 (儘管有些需要重構的部分可能已經過時)。

如果我升等到 Vue 2 ,我還必須同時升級 Vuex 和 Vue Router?

只有 Vue Router 2 與 Vue 2 保持相容,所以 Vue Router 是需要升級的,你必須遵循 Vue Router 遷移方式來處理。幸運的是,大多數應用程式沒有很多 router 相關程式碼,所以遷移可能不會超過一個小時。

對於 Vuex ,版本 0.8 與 Vue 2 保持相容,所以部分不必強制升級。可以促使你立即升級的唯一理由,是你想要使用那些 Vuex 2 中新的高級特性,例如模組 (modules) 和減少的樣板檔案 (reduced boilerplate)。


範本



片段實例移除

每個元件必須只有一個根元素。不再允許片段實例,如果你有這樣的模板:###
<p>foo</p>
<p>bar</p>
###最好把整個內容都簡單包裹到一個新的元素裡,如下所示:###
<div>
  <p>foo</p>
  <p>bar</p>
</div>

升級方式

升級後運行端對端測試套件(end-to-end test suite) 或運行應用程序,並查看控制台警告(console warnings) 來找出那些範本中有多個根元素的地方。


生命週期鉤子函數



beforeCompile移除


使用created 鉤子函數替代。

升級方式

在程式碼庫中執行
遷移工具

來找出所有使用此鉤子函數的範例。

compiled


##取代 使用mounted 鉤子函數取代。 升級方式

在程式碼庫中執行

遷移工具
來找出所有使用此鉤子函數的範例。

attached


##移除

使用其他鉤子函數內建的DOM 偵測(DOM check) 方法。例如,替換如下:

attached: function () {
  doSomething()
}
可以這樣使用:
mounted: function () {
  this.$nextTick(function () {
    doSomething()
  })
}
#升級方式

在程式碼庫中執行

遷移工具

來找出所有使用此鉤子函數的範例。 ##### ###移除## #############使用其他鉤子函數內的DOM 來偵測(DOM check) 方法。例如,替換如下:###
detached: function () {
  doSomething()
}
###可以這樣使用:###
destroyed: function () {
  this.$nextTick(function () {
    doSomething()
  })
}
#############升級方式############在程式碼庫中執行###遷移工具###來找出所有使用此鉤子函數的範例。 ######


init 重新命名

##使用新的

beforeCreate
鉤子函數來取代,本質上beforeCreate 和init 完全相同。 init 被重新命名是為了和其他的生命週期方法的命名方式保持一致。

升級方式

在程式碼庫中執行

遷移工具
來找出所有使用此鉤子函數的範例。


ready 取代

使用新的mounted 鉤子函數取代。應該注意的是,使用 mounted 並不能保證鉤子函數中的 this.$el 在 document 中。為此也應該引入 Vue.nextTick/

vm.$nextTick
。例如:

mounted: function () {
  this.$nextTick(function () {
    // 代码保证 this.$el 在 document 中
  })
}
升級方式

#在程式碼庫中執行

遷移工具
來找出所有使用此鉤子函數的範例。


v-for



v-for# 遍歷陣列時的參數順序變更

當包含index 時,之前遍歷陣列時的參數順序是(index, value)。現在是 (value, index) ,來和 JavaScript 的原生陣列方法 (例如 forEach

map
) 保持一致。

升級方式

在程式碼庫中執行遷移工具來找出那些使用舊有參數順序的範例。請注意,如果你將你的 index 參數命名為一些不通用的名字 (例如 position 或 

num
),遷移工具將不會標記它們。 ######


v-for# 遍歷物件時的參數順序變更

當包含property 名稱/key 時,先前遍歷物件的參數順序是(name, value)。現在是 (value, name),來和常見的物件迭代器 (例如 lodash) 保持一致。

升級方式

在程式碼庫中執行遷移工具來找出那些使用舊有參數順序的範例。請注意,如果你將你的 key 參數命名為一些不通用的名字 (例如 name 或 property),遷移工具將不會標記它們。


$index$key 移除

已經移除了$index$key 這兩個隱式聲明變量,以便在v-for 中明確定義。這可以使沒有太多 Vue 開發經驗的開發者更好地閱讀程式碼,並且在處理巢狀循環時也能產生更清晰的行為。

升級方式

在程式碼庫中執行遷移工具來找出使用這些移除變數的範例。如果你沒有找到,也可以在控制台錯誤中找到 (例如 Uncaught ReferenceError: $index is not defined)。


track-bytrack-by

##取代track-by 已經被替換為

key

,它的工作方式與其他屬性一樣,沒有

v-bind

: 前綴,它會被當作字串處理。在多數情況下,你需要使用具有完整表達式的動態綁定 (dynamic binding) 來取代靜態的 key。例如,替換:

<div v-for="item in items" track-by="id">
你現在應該寫為:
<div v-for="item in items" v-bind:key="item.id">

#升級方式

##在程式碼庫中執行
遷移工具###來找出那些使用###track-by###的範例。 ######


v-for# 範圍值變更##在

#之前,

v-for="number in 10"number 從0 開始到9 結束,現在從1 開始,到10 結束。

升級方式

在程式碼庫中使用正規 

/\w in \d /搜尋。當出現在 v-for 中,請檢查是否受到影響。


Props



coerce

Prop 的參數

移除
  • 如果需要檢查prop 的值,建立一個內部的computed 值,而不再在props 內部去定義,例如:
  • props: {
      username: {
        type: String,
        coerce: function (value) {
          return value
            .toLowerCase()
            .replace(/\s+/, '-')
        }
      }
    }

    現在應該寫為:

    props: {
      username: String,
    },
    computed: {
      normalizedUsername: function () {
        return this.username
          .toLowerCase()
          .replace(/\s+/, '-')
      }
    }
  • 這樣有一些好處:

你可以對保持原始prop 值的操作權限。

透過給予驗證後的值一個不同的命名,強制開發者使用明確申明。

升級方式


#執行遷移工具找出包含  coerce 選項的實例。

twoWay

  • Prop 的參數移除

  • Props 現在只能單向傳遞。為了對父元件產生反向影響,子元件需要明確地傳遞一個事件而不是依賴隱式地雙向綁定。詳見:

  • 自訂元件事件

#自訂輸入元件
(使用元件事件)

全域狀態管理

升級方式#### ########執行###遷移工具###,找出含有 ###twoWay### 參數的實例。 ######


v-bind# 的.once.sync 修飾符移除

Props 現在只能單向傳遞。為了對父元件產生反向影響,子元件需要明確地傳遞一個事件而不是依賴隱式地雙向綁定。詳見:

升級方式

執行遷移工具找到使用 .once 和 .sync 修飾符的實例。


修改Props 棄用

元件內修改prop是反模式(不建議的) 的。例如,先宣告一個 prop ,然後在元件中透過 this.myProp = 'someOtherValue' 改變 prop 的值。根據渲染機制,當父元件重新渲染時,子元件的內部 prop 值也會被覆寫。

大多數情況下,改變 prop 值可以用以下選項取代:

  • #透過 data 屬性,用 prop 去設定一個 data 屬性的預設值。

  • 透過 computed 屬性。

升級方式

#運行端對端測試,查看關於prop 修改的控制台警告訊息


根實例的Props 替換

對於一個根實例來說(例如:用new Vue({ ... }) 建立的實例),只能用propsData 而不是props

升級方式

執行端對端測試,將會彈出 failed tests 來通知你使用props 的根實例已經失效。


計算屬性



#cache: false 棄用

在Vue 未來的大版本中,計算屬性的快取驗證將會被移除。把不緩存的計算屬性轉換成方法可以得到和之前相同的結果。

範例:

template: '<p>message: {{ timeMessage }}</p>',
computed: {
  timeMessage: {
    cache: false,
    get: function () {
      return Date.now() + this.message
    }
  }
}

或使用元件方法:

template: '<p>message: {{ getTimeMessage() }}</p>',
methods: {
  getTimeMessage: function () {
    return Date.now() + this.message
  }
}

#升級方式


##執行遷移工具找到 cache: false

 的選項。


Built-In 指令
##v-bind

真/假值變更在2.0中使用v-bind 時,只有null,

undefined

,和false 被視為假。這意味著,0 和空字串將被當作真值渲染。例如

v-bind:draggable="''"
將會被渲染為

draggable="true"對於枚舉屬性,除了上述假值之外,字串 "false"

也會被渲染為
attr="false"

注意,對於其它鉤子函數 (如 v-if# 和 

v-show

),他們依然遵循 js 對真假值判斷的一般規則。


升級方式#執行端對端測試,如果你app 的任何部分有可能會被這個升級影響到,將會彈出failed tests

#用v-on 監聽原生事件變更

#現在在元件上使用v-on 只會監聽自訂事件(元件用$emit

觸發的事件)。如果要監聽根元素的原生事件,可以使用

.native 修飾符,例如:

<my-component v-on:click.native="doSomething"></my-component>

######升級方式####### ####在程式碼庫中執行###遷移工具###來找出所有使用此鉤子函數的範例。 ######


debouncev-model移除

Debouncing 曾經被用來控制Ajax 請求及其它高耗任務的頻率。 Vue 中v-modeldebounce 屬性參數使得在一些簡單情況下非常容易實現這種控制。但實際上,這是控制了狀態更新的頻率,而不是控制高耗時任務本身。這是個微小的差別,但是會隨著應用成長而顯現出限制。

例如設計搜尋提示時的限制:

1.gif

使用 debounce 參數,便無法觀察「Typing」 的狀態。因為無法對輸入狀態進行即時檢測。然而,透過將 debounce 與Vue 解耦,可以只延遲我們想要控制的操作,從而避開這些限制:

<!--
通过使用 lodash 或者其它库的 debounce 函数,
我们相信 debounce 实现是一流的,
并且可以随处使用它,不仅仅是在模板中。
-->
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.js"></script>
<div id="debounce-search-demo">
  <input v-model="searchQuery" placeholder="Type something">
  <strong>{{ searchIndicator }}</strong>
</div>
new Vue({
  el: '#debounce-search-demo',
  data: {
    searchQuery: '',
    searchQueryIsDirty: false,
    isCalculating: false
  },
  computed: {
    searchIndicator: function () {
      if (this.isCalculating) {
        return '⟳ Fetching new results'
      } else if (this.searchQueryIsDirty) {
        return '... Typing'
      } else {
        return '✓ Done'
      }
    }
  },
  watch: {
    searchQuery: function () {
      this.searchQueryIsDirty = true
      this.expensiveOperation()
    }
  },
  methods: {
    // 这是 debounce 实现的地方。
    expensiveOperation: _.debounce(function () {
      this.isCalculating = true
      setTimeout(function () {
        this.isCalculating = false
        this.searchQueryIsDirty = false
      }.bind(this), 1000)
    }, 500)
  }
})

這種方式的另一個優點是:當包裹函數執行時間與延遲時間相當時,將會等待較長時間。例如,當給予搜尋建議時,要等待使用者輸入停止一段時間後才給予建議,這個體驗非常差。其實,這時候比較適合用 throttling 函數。因為現在你可以自由的使用類似 lodash 之類的函式庫,所以很快就可以用 throttling 重構項目。

Upgrade Path

#執行 遷移工具使用 debounce 參數的實例。


使用lazynumber 參數的v-model替換

lazynumber 參數現在以修飾符的形式使用,看起來更清晰,而不是這樣:

<input v-model="name" lazy>
<input v-model="age" type="number" number>

現在寫成這樣:

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

#升級方式

執行遷移工具找到這些棄用參數。


使用內嵌valuev-model 移除

v-model 不再以內嵌value 方式初始化的初步值了,顯然他將以實例的data 對應的屬性作為真正的初值。

這表示以下元素:

<input v-model="text" value="foo">

在 data 選項中有下面寫法的:

data: {
  text: 'bar'
}

將渲染 model 為 ‘bar’ 而不是 ‘foo’ 。同樣,對<textarea> 已有的值來說:

<textarea v-model="text">
  hello world
</textarea>

必須保證text 初值為「hello world」

#升級方式

升級後執行端對端測試,注意關於v-model內聯參數的 console warnings


v-model# with v-for Iterated Primitive Values 移除

#像這樣的寫法將會失效:

<input v-for="str in strings" v-model="str">

因為< ;input> 將會被編譯成類似下面的js 程式碼:

strings.map(function (str) {
  return createElement('input', ...)
})

這樣,v-model 的雙向綁定在這裡就失效了。把 str 賦值給迭代器裡的另一個值也沒有用,因為它只是函數內部的一個變數。

替代方案是,你可以使用物件數組,這樣v-model 就可以同步更新物件裡面的欄位了,例如:

<input v-for="obj in objects" v-model="obj.str">

升級方式

執行測試,如果你的app 有地方被這個更新影響到的話將會彈出failed tests提示。


#有!importantv-bind:style 移除

這樣寫將失效:

<p v-bind:style="{ color: myColor + ' !important' }">hello</p>

如果確實需要覆寫其它的!important,最好用字串形式去寫入:

<p v-bind:style="'color: ' + myColor + ' !important'">hello</p>

升級方式

#執行 遷移幫助工具。找出含有 !important 的 style 綁定物件。


v-el# 和v-ref 替換

簡單起見,v-elv-ref 合併為一個ref 屬性了,可以在元件實例中透過$refs 來呼叫。這意味著v-el:my-element 將寫成這樣:ref="myElement"v-ref:my-component 變成這樣: ref="myComponent"。綁定在一般元素上時,ref 指 DOM 元素,綁定在元件上時,ref 為一元件實例。

因為 v-ref 不再是一個指令了而是一個特殊的屬性,它也可以被動態定義了。這樣在和v-for 結合的時候是很有用的:

<p v-for="item in items" v-bind:ref="'item' + item.id"></p>

以前v-el/v-refv-for 一起使用將產生一個DOM 陣列或元件數組,因為沒辦法給每個元素一個特定名字。現在你還仍然可以這樣做,給每個元素一個相同的ref

<p v-for="item in items" ref="items"></p>

和1.x 中不同,$refs 不是回應的,因為它們在渲染過程中註冊/更新。只有監聽變化並重複渲染才能使它們響應。

另一方面,設計$refs主要是提供給 js 程式存取的,並不建議在模板中過度依賴使用它。因為這意味著在實例之外去存取實例狀態,違背了 Vue 資料驅動的想法。

升級方式

執行遷移工具找出實例中的 v-el 和 v-ref 。


v-show後面使用 v-else 移除

v-else 不能再跟在v-show#後面使用。請在v-if的否定分支中使用v-show來取代。例如:

<p v-if="foo">Foo</p>
<p v-else v-show="bar">Not foo, but bar</p>

現在應該寫出這樣:

<p v-if="foo">Foo</p>
<p v-if="!foo && bar">Not foo, but bar</p>

#升級方式

執行遷移工具找出實例中存在的 v-else 以及 v-show


自訂指令簡化


#在新版中,指令的使用範圍已經大大減小了:現在指令僅僅被用於低階的DOM 操作。大多數情況下,最好是使用元件作為程式碼重複使用的抽象層。

顯要的改變有以下幾點:

  • 指令不再擁有實例。意思是,在指令的鉤子函數中不再擁有實例的 this 。替代的是,你可以在參數中接受你需要的任何資料。如果確實需要,可以透過 el 來存取實例。

  • 類似 acceptStatementdeeppriority 等都已被棄用。為了替換雙向指令,請參閱 範例

  • 現在有些鉤子的意義和以前不一樣了,並且多了兩個鉤子函數。

幸運的是,新鉤子更簡單,更容易掌握。詳見 自訂指令指南

升級方式

執行遷移工具找出定義指令的地方。在 helper 工具會把這些地方標記出來,因為很有可能這些地方需要重構。


指令.literal 修飾符移除

.literal 修飾符已經被移除,為了取得相同的功能,可以簡單地提供字串修飾符作為值。

範例,如下變更:

<p v-my-directive.literal="foo bar baz"></p>

只是:

<p v-my-directive="'foo bar baz'"></p>

升級方式

################################執行###遷移工具###找出實例中使用`.literal` 修飾符的地方。 ######


過渡



transition 參數取代

#Vue 的過渡系統有了徹底的改變,現在透過使用<transition><transition-group> 來包裹元素實現過渡效果,而不再使用transition

屬性。詳見
Transitions guide

升級方式

運行遷移工具

找到使用 
transition

 屬性的地方。

可重複使用的過渡Vue.transition 取代

在新的過渡系統中,可以
透過模板重複使用過渡效果

升級方式

運行遷移工具

找到使用 
transition

 屬性的地方。

過渡的stagger 參數移除

如果希望在清單渲染中使用漸近過渡,可以透過設定元素的data-index

(或類似屬性) 來控制時間。請參考
這個範例

升級方式

運行遷移工具

找到使用 
transition### 屬性的地方。升級期間,你可以「過渡」到新的過渡策略。 ######


事件



events 選項移除

#events 選項被棄用。事件處理器現在在 created 鉤子中被註冊。參考詳細範例$dispatch and

$broadcast

遷移指南

##Vue.directive('on').keyCodes#取代

新的簡明配置keyCodes 的方式是透過

Vue.config.keyCodes
例如:

// v-on:keyup.f1 不可用
Vue.config.keyCodes.f1 = 112
升級方式

#執行遷移工具找到過時的 

keyCode
 設定######


$dispatch# 和$broadcast 替換

$dispatch$broadcast 已經被棄用。請使用更多簡潔清晰的元件間通訊和更好的狀態管理方案,如:Vuex

因為基於元件樹結構的事件流方式實在是讓人難以理解,並且在元件結構擴展的過程中會變得越來越脆弱。這種事件方式確實不太好,我們也不希望在以後讓開發者太痛苦。且$dispatch$broadcast 也沒有解決兄弟組件間的通訊問題。

對於$dispatch$broadcast最簡單的升級方式就是:透過使用事件中心,允許元件自由交流,無論元件處於元件樹的哪一層。由於 Vue 實例實作了一個事件分發接口,你可以透過實例化一個空的 Vue 實例來實現這個目的。

這些方法最常見的用途之一是父子元件的相互通訊。在這些情況下,你可以使用 v-on 監聽子元件上 $emit 的變化。這可以允許你很方便的添加事件顯性。

然而,如果是跨多層父子元件溝通的話,$emit 並沒有什麼用。相反,用集中式的事件中間件可以做到簡單的升級。這會讓組件之間的通訊非常順利,即使是兄弟組件。因為 Vue 透過事件發射器介面執行實例,實際上你可以使用一個空的 Vue 實例。

例如,假設我們有todo 的應用結構如下:

Todos
├─ NewTodoInput
└─ Todo
   └─ DeleteTodoButton

可以透過單獨的事件中心管理元件間的通訊:

// 将在各处使用该事件中心
// 组件通过它来通信
var eventHub = new Vue()

然後在元件中,可以使用$emit, $on, $off 分別來分發、監聽、取消監聽事件:

// NewTodoInput
// ...
methods: {
  addTodo: function () {
    eventHub.$emit('add-todo', { text: this.newTodoText })
    this.newTodoText = ''
  }
}
// DeleteTodoButton
// ...
methods: {
  deleteTodo: function (id) {
    eventHub.$emit('delete-todo', id)
  }
}
// Todos
// ...
created: function () {
  eventHub.$on('add-todo', this.addTodo)
  eventHub.$on('delete-todo', this.deleteTodo)
},
// 最好在组件销毁前
// 清除事件监听
beforeDestroy: function () {
  eventHub.$off('add-todo', this.addTodo)
  eventHub.$off('delete-todo', this.deleteTodo)
},
methods: {
  addTodo: function (newTodo) {
    this.todos.push(newTodo)
  },
  deleteTodo: function (todoId) {
    this.todos = this.todos.filter(function (todo) {
      return todo.id !== todoId
    })
  }
}

在簡單的情況下這樣做可以替代$dispatch$broadcast,但是對於大多數複雜情況,更推薦使用一個專用的狀態管理層如:Vuex

升級方式

執行遷移工具找出使用 $dispatch 和$broadcast的實例。


過濾器




#插入文字以外的篩選器移除

現在篩選器只能用在插入文字中(

{{ }}
tags)。我們發現在指令 (如:

v-model

v-on等) 中使用篩選器使事情變得更複雜。像 v-for 這樣的列表過濾器最好把處理邏輯當作一個計算屬性放在 js 裡面,這樣就可以在整個模板中重複使用。

總之,能在原生 js 中實現的東西,我們盡量避免引入一個新的符號去重複處理同樣的問題。以下是如何取代Vue 內建過濾器:

取代debounce 過濾器

#不再這樣寫

<input v-on:keyup="doStuff | debounce 500">
methods: {
  doStuff: function () {
    // ...
  }
}
請使用lodash's

debounce


# (也有可能是

throttle) 來直接控制高耗任務。可以這樣來實現上面的功能:

<input v-on:keyup="doStuff">
methods: {
  doStuff: _.debounce(function () {
    // ...
  }, 500)
}
這種寫法的更多優點詳見:

v-model

範例。

取代

limitBy

篩選器

就不再這樣寫:

<p v-for="item in items | limitBy 10">{{ item }}</p>
在computed 屬性中使用js 內建方法:.slice

method

<p v-for="item in filteredItems">{{ item }}</p>
computed: {
  filteredItems: function () {
    return this.items.slice(0, 10)
  }
}

#取代filterBy

過濾器

不再這樣寫:

<p v-for="user in users | filterBy searchQuery in 'name'">{{ user.name }}</p>

在computed 屬性中使用js 內建方法

.filter

method

<p v-for="user in filteredUsers">{{ user.name }}</p>
computed: {
  filteredUsers: function () {
    var self = this
    return self.users.filter(function (user) {
      return user.name.indexOf(self.searchQuery) !== -1
    })
  }
}
js 原生的.filter

同樣能實現許多複雜的過濾器操作,因為可以在計算computed 屬性中使用所有js 方法。例如,想要透過匹配使用者名字和電子郵件地址(不區分大小寫) 找到使用者:

var self = this
self.users.filter(function (user) {
  var searchRegex = new RegExp(self.searchQuery, 'i')
  return user.isActive && (
    searchRegex.test(user.name) ||
    searchRegex.test(user.email)
  )
})

#取代orderBy 過濾器不這樣寫:

<p v-for="user in users | orderBy 'name'">{{ user.name }}</p>

而是在computed 屬性中使用

lodash's
orderBy

(或者可能是sortBy

):

<p v-for="user in orderedUsers">{{ user.name }}</p>
computed: {
  orderedUsers: function () {
    return _.orderBy(this.users, 'name')
  }
}
甚至可以欄位排序:
_.orderBy(this.users, ['name', 'last_login'], ['asc', 'desc'])

##升級方式
####### ##執行###遷移工具###找到指令中使用的篩選器。如果有些沒找到,看看###控制台錯誤訊息###。 ######


篩選器參數符號變更

#現在篩選器參數形式可以更好地與js 函數呼叫方式一致,因此不用再用空格分隔參數:

<p>{{ date | formatDate 'YY-MM-DD' timeZone }}</p>

現在用圓括號括起來並用逗號分隔:

<p>{{ date | formatDate('YY-MM-DD', timeZone) }}</p>

##升級方式

執行

遷移工具找到老式的呼叫符​​號,如果有遺漏,請看控制台錯誤訊息


內建文字過濾器移除

#儘管插入文字內部的過濾器仍然有效,但是所有內建過濾器已經移除了。取代的是,推薦在每個區域使用更專業的庫來解決。 (例如用 date-fns 來格式化日期,用 accounting 來格式化貨幣)。

對於每個內建過濾器,我們大概總結了下該怎麼替換。程式碼範例可能寫在自訂 helper 函數,方法或計算屬性中。


取代json 過濾器

不用一個個改,因為Vue 已經幫你自動格式化好了,無論是字串,數字還是數組,物件。如果想用 js 的 JSON.stringify 功能去實現,你也可以把它寫在方法或計算屬性裡面。


取代capitalize 過濾器

text[0].toUpperCase() + text.slice(1)


替換uppercase 過濾器

text.toUpperCase()


取代lowercase 過濾器

#
text.toLowerCase()


替換pluralize 過濾器

#NPM 上的pluralize 庫可以很好的實作這個功能。如果僅僅想將特定的單字格式化成複數形式或想給特定的值('0') 指定特定的輸出,也可以很容易地自訂複數格式化過濾器:

function pluralizeKnife (count) {
  if (count === 0) {
    return 'no knives'
  } else if (count === 1) {
    return '1 knife'
  } else {
    return count + 'knives'
  }
}


Replacing the currency Filter

對於簡單的問題,可以這樣做:

'$' + price.toFixed(2)

大多數情況下,仍然會有奇怪的現象(例如0.035.toFixed(2) 向上取捨得到0.04,但是0.045 向下取捨卻也得到0.04)。解決這些問題可以使用 accounting 函式庫來實現更多可靠的貨幣格式化。

升級方式

運行遷移工具找到捨棄的過濾器。如果有些遺漏,請參考控制台錯誤訊息


雙向過濾器取代

#有些使用者已經樂於透過v- model 使用雙向過濾器,以很少的程式碼創建有趣的輸入。儘管表面上很簡單,雙向濾鏡也會暗藏一些巨大的複雜性——甚至促使狀態更新變得遲鈍影響使用者體驗。推薦用包裹一個輸入的元件取而代之,這樣以更顯性且功能更豐富的方式建立自訂的輸入。

我們現在做一個雙向匯率過濾器的遷移作為示範:

它基本上運作良好,但是拖延的狀態更新會導致奇怪的行為。例如,點選 Result 標籤,試著在其中一個輸入方塊中輸入 9.999。當輸入框失去焦點的時候,其值將會更新到 $10.00。然而當我們從整個計算器的角度看時,你會發現儲存的資料是 9.999。用戶看到的已經不是真實的同步了!

為了過渡到一個更強壯的Vue 2.0 的方案,讓我們先在一個新的 <currency-input> 組件中包裹這個過濾器:

它允許我們加入獨立過濾器無法封裝的行為,例如選擇輸入框聚焦的內容。下一步我們從過濾器中提取業務邏輯。接下來是我們把所有的東西放到一個外在的 currencyValidator 物件

##這會更加模組化,不只是更容易的遷移到Vue 2,同時也允許匯率間隙和格式化:

  • 從你的Vue 程式碼中獨立出來進行單元測試

  • 在你的應用程式的別的部分中使用,例如驗證驗證一個API 端的負荷

把這個驗證器提取出來之後,我們也可以更舒適的把它構建到更健壯的解決方案中。那些古怪的狀態也消除了,用戶不再可能會輸入錯誤,就像瀏覽器原生的數位輸入框一樣。

然而在Vue 1.0 的過濾器中,我們仍然是受限的,所以還是完全升級到Vue 2.0 吧:

你可能注意到了:

  • 我們的輸入框的各方面都更顯性,使用生命週期鉤子和 DOM 事件以取代雙向過濾器的隱藏行為。

  • 我們現在可以在自訂輸入框中直接使用v-model,其不只是固定配合正常的輸入框來使用,這也意味著我們的組件是對Vuex 友​​好的。

  • 因為我們已經不再要求篩選器選項必須要有一個回傳值,所以實際上我們的匯率工作可以非同步完成。這意味著如果我們有很多應用需要和匯率打交道,我們可以輕鬆的提煉這個邏輯並成為一個共享的微服務。

升級方式

#執行遷移工具找到在例如  v-model 的指令中使用過濾器的範例。如果你錯過了,則應該會收到命令列報錯誤





重名的插槽移除

#同一範本中的重名<slot>已經棄用。當一個插槽已經被渲染過了,那麼就不能在同一模板其它地方被再次渲染了。如果要在不同位置渲染相同內容,可以用 prop 來傳遞。


升級方式

更新後執行測試,請查看控制台警告訊息 關於重名slots 的提示 v-model

slot 樣式參數

移除######升級方式############運行###遷移工具###找到選擇slots 標籤CSS 選擇器(例如:## #[slot="my-slot-name"]###)。 ######


特殊屬性



#keep-alive 屬性取代

keep-alive 不再是一個特殊屬性而是一個包裹元件,類似於<transition>例如:

<keep-alive>
  <component v-bind:is="view"></component>
</keep-alive>

這樣可以在包含多種狀態子元件中使用 <keep-alive>

<keep-alive>
  <todo-list v-if="todos.length > 0"></todo-list>
  <no-todos-gif v-else></no-todos-gif>
</keep-alive>

當 <keep-alive> 含有不同子元件時,應該分別影響每個子元件。不只是第一個而是所有的子元件都將被忽略。

<transition>一起使用時,請確保把內容包裹在內:

<transition>
  <keep-alive>
    <component v-bind:is="view"></component>
  </keep-alive>
</transition>

升級方式

執行遷移工具找到keep-alive 屬性。


#計算插值




##屬性內部的計算插值

移除

#屬性內部的計算插值已經不能再使用了:

<button class="btn btn-{{ size }}"></button>

應該寫成行內表達式:

<button v-bind:class="'btn btn-' + size"></button>
或計算屬性:
<button v-bind:class="buttonClasses"></button>
computed: {
  buttonClasses: function () {
    return 'btn btn-' + size
  }
}


升級方式

運行遷移工具找到屬性內部的計算插值

#HTML 計算插值移除

HTML 的計算插值({{{ foo }}}) 已經移除,取代的是

v-html

指令

######升級方式############執行###遷移工具###找到 HTML 計算插值。 ######


單次綁定取代

#單次綁定({ {* foo }}) 已被新的v-once directive 取代。

升級方式

運行遷移工具找到單次綁定使用位置。


回應



vm.$watch

changed

透過 vm.$watch所建立的觀察器現在將在元件渲染時啟動。這樣可以讓你在元件渲染前更新狀態,不用做不必要的更新。例如可以透過觀察元件的 prop 變化來更新元件本身的值。

如果以前透過

vm.$watch

在元件更新後與 DOM 交互,現在就可以透過
updated

生命週期鉤子來做這些。

升級方式執行測試,如果有依賴舊方法的觀察器會彈出 failed tests。

vm.$set

變更

vm.$set

只是

Vue.set

的別名。


升級方式執行遷移工具找到過時的用法

#vm.$delete

變更

vm.$delete

現在只是:

Vue.delete

別名。
############升級方式############執行###遷移工具###找到過時的用法#######


Array.prototype.$set 棄用

Vue. set 替代

升級方式

#運行遷移工具找到陣列上的 .$set。如有遺漏請參考控制台錯誤訊息


Array.prototype.$remove# #移除

Array.prototype.splice 取代,例如:

methods: {
  removeTodo: function (todo) {
    var index = this.todos.indexOf(todo)
    this.todos.splice(index, 1)
  }
}

或更好的方法,直接給除去的方法一個index 參數:

methods: {
  removeTodo: function (index) {
    this.todos.splice(index, 1)
  }
}

升級方式

#執行

遷移工具找到陣列上的.$remove。如有遺漏請參考控制台錯誤訊息


Vue 實例上的Vue.setVue.delete移除

Vue.setVue.delete 在實例上將不再運作。現在都強制在實例的 data 選項中聲明所有頂級回應值。如果刪除實例屬性或實例$data上的某個值,直接將它設為 null 即可。

升級方式

執行

遷移工具找到實例中的 Vue.set 或 Vue.delete 。如有遺漏請參考控制台錯誤訊息


#vm.$data 移除

現在禁止替換實例的$data。這樣防止了響應系統的一些極端情況並且讓組件狀態更加可控可預測 (特別是對於存在類型檢查的系統)。

升級方式

運行

遷移工具找到覆寫 vm.$data的位置。如有遺漏請參考 控制台警告訊息


vm.$get 移除

#可以直接取回回應資料。

升級方式

運行遷移工具找到 vm.$get 的位置。如有遺漏請參考 控制台錯誤訊息


圍繞DOM 的實例方法



##vm.$appendTo# 移除

使用DOM 原生方法:

myElement.appendChild(vm.$el)


升級方式

執行遷移工具找到 vm.$appendTo 的位置。如果有遺漏可以參考 控制台錯誤訊息

vm.$before

移除使用DOM 原生方法:

myElement.parentNode.insertBefore(vm.$el, myElement)


升級方式

執行遷移工具找到 vm.$before。如有遺漏,請參考 控制台錯誤訊息

vm.$after

移除

使用DOM 原生方法:

myElement.parentNode.insertBefore(vm.$el, myElement.nextSibling)
如果myElement 是最後一個節點也可以這樣寫:
myElement.parentNode.appendChild(vm.$el)

## #####升級方式############執行###遷移工具###找到 ###vm.$after### 的位置。如有遺漏,請參考 ###控制台錯誤訊息###。 ######


vm.$remove 移除

使用DOM 原生方法:

vm.$el.remove()

#升級方式

執行遷移工具找到vm.$remove。如有遺漏,請參考 控制台錯誤訊息


#底層實例方法



vm.$eval 移除

盡量不要使用,如果必須使用該功能且不肯定如何使用請參考the forum

升級方式

執行遷移工具找到使用 vm.$eval的位置。如有遺漏請參考 控制台錯誤訊息


vm.$interpolate 移除

盡量不要使用,如果必須使用該功能且不肯定如何使用請參考the forum

升級方式

運行遷移工具找到vm.$interpolate。如有遺漏請參考 控制台錯誤訊息


vm.$log##。除

請使用

Vue Devtools 感受最佳debug 體驗。

升級方式

執行

遷移工具找到 ##vm.$log。如有遺漏請參考控制台錯誤訊息。


實例DOM 選項



replace: false 移除

現在元件總是會替換掉他們被綁定的元素。為了模仿replace: false的行為,可以用一個和將要替換元素類似的元素將根元件包起來:

new Vue({
  el: '#app',
  template: '<div id="app"> ... </div>'
})

或使用渲染函數:

new Vue({
  el: '#app',
  render: function (h) {
    h('div', {
      attrs: {
        id: 'app',
      }
    }, /* ... */)
  }
})

#升級方式

執行遷移工具找到 replace: false 所使用的位置。


#全域配置




##Vue.config.debug

移除

不再需要,因為警告訊息將預設在堆疊資訊裡輸出。

升級方式

運行遷移工具找到包含Vue.config.debug的地方。

Vue.config.async

移除

非同步操作現在需要渲染效能的支援。

升級方式

運行遷移工具找到使用Vue.config.async 的實例。

Vue.config.delimiters

替換

模板選項的方式使用。這樣可以在使用自訂分隔符號時避免影響第三方範本。

###升級方式############運行###遷移工具###找到使用###Vue.config.delimiters## # 的實例。 ######


Vue.config.unsafeDelimiters 移除

HTML 插值替換為 v-html

升級方式

運行遷移工具來找到 Vue.config.unsafeDelimiters。然後 helper 工具也會找到 HTML 插入的實例,可以用`v-html`來取代。


#全域API




##帶

el

Vue.extend 移除

##el 選項不再在Vue.extend中使用。僅在實例建立參數中可用。

升級方式


更新後運行測試在​​控制台警告資訊中找到關於帶有Vue.extendel

Vue.elementDirective

##移除

用元件來取代

####升級方式###########執行# ##遷移工具###找到包含###Vue.elementDirective###的實例。 ######


Vue.partial 移除

Partials 已被移除,取而代之的是更明確的元件之間的資料流–props。除非你正在使用一個部分性能關鍵型區域,否則建議只使用一個 normal component 來代替。如果你是動態綁定部分的 name,你可以使用 dynamic component

如果你碰巧在你的應用程式的效能關鍵部分使用 partials,那麼你應該升級到函數式元件。它們必須在純 JS / JSX 檔案中 (而不是在 .vue 檔案中),並且是無狀態的和無實例的,就像 partials。這使得渲染極快。

函數式元件相對於 partials 一個好處是它們可以更具動態性,因為它們允許您存取 JavaScript 的全部功能。然而,這是有成本的。如果你從來沒有使用過渲染式的元件框架,你可能需要花更長的時間來學習它們。

升級方式

執行遷移工具找到包含 Vue.partial的實例