## FAQ
> 哇,非常長的一頁!是否意味著 Vue 2.0 已經完全不同了呢,是否需要從頭學起呢,Vue 1.0 的項目是不是沒法遷移了?
非常開心地告訴你,并不是!幾乎 90% 的 API 和核心概念都沒有變。因為本節包含了很多詳盡的闡述以及許多遷移的例子,所以顯得有點長。不用擔心,**你不必從頭到尾把本節讀一遍!**
> 我該從哪里開始項目遷移呢?
1. 首先,在當前項目下運行[遷移工具](https://github.com/vuejs/vue-migration-helper)。我們非常謹慎地把高級 Vue 升級過程簡化為使用一個簡單的命令行工具。當工具識別出舊有的特性后,就會告知你并給出建議,同時附上關于詳細信息的鏈接。
2. 然后,瀏覽本頁面的側邊欄列出的內容。如果發現有的標題對你的項目有影響,但是遷移工具沒有給出提示,請檢查自己的項目。
3. 如果你的項目有測試代碼,運行并查看仍然失敗的地方。如果沒有測試代碼,在瀏覽器中打開你的程序,通過導航環顧并留意那些報錯或警告信息。
4. 現在,你的應用程序應該已徹底完成遷移。如果你渴望了解更多,可以閱讀本頁面剩余部分 - 或者從[介紹](index.html)部分,從頭開始深入新的文檔和改進過的指南。由于你已經熟悉一些核心概念,所以許多部分已經被刪除掉。
> 將 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 遷移方式](migration-vue-router.html)來處理。幸運的是,大多數應用沒有很多 router 相關代碼,所以遷移可能不會超過一個小時。
對于 Vuex ,版本 0.8+ 與 Vue 2 保持兼容,所以部分不必強制升級。可以促使你立即升級的唯一理由,是你想要使用那些 Vuex 2 中新的高級特性,比如模塊 (modules) 和減少的樣板文件 (reduced boilerplate)。
## 模板
### 片段實例 <sup>移除</sup>
每個組件必須只有一個根元素。不再允許片段實例,如果你有這樣的模板:
``` html
<p>foo</p>
<p>bar</p>
```
最好把整個內容都簡單包裹到一個新的元素里,如下所示:
``` html
<div>
<p>foo</p>
<p>bar</p>
</div>
```
## 生命周期鉤子函數
### `beforeCompile` <sup>移除</sup>
使用 `created` 鉤子函數替代。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>來找出所有使用此鉤子函數的示例。</p>
</div>
```
### `compiled` <sup>替換</sup>
使用 `mounted` 鉤子函數替代。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>來找出所有使用此鉤子函數的示例。</p>
</div>
```
### `attached` <sup>移除</sup>
使用其他鉤子函數內置的 DOM 檢測 (DOM check) 方法。例如,替換如下:
``` js
attached: function () {
doSomething()
}
```
可以這樣使用:
``` js
mounted: function () {
this.$nextTick(function () {
doSomething()
})
}
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>來找出所有使用此鉤子函數的示例。</p>
</div>
```
### `detached` <sup>移除</sup>
使用其他鉤子函數內的 DOM 檢測 (DOM check) 方法。例如,替換如下:
``` js
detached: function () {
doSomething()
}
```
可以這樣使用:
``` js
destroyed: function () {
this.$nextTick(function () {
doSomething()
})
}
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>來找出所有使用此鉤子函數的示例。</p>
</div>
```
### `init` <sup>重新命名</sup>
使用新的 `beforeCreate` 鉤子函數替代,本質上 beforeCreate 和 init 完全相同。init 被重新命名是為了和其他的生命周期方法的命名方式保持一致。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>來找出所有使用此鉤子函數的示例。</p>
</div>
```
### `ready` <sup>替換</sup>
使用新的 `mounted` 鉤子函數替代。應該注意的是,使用 `mounted` 并不能保證鉤子函數中的 this.$el 在 document 中。為此還應該引入 `Vue.nextTick`/`vm.$nextTick`。例如:
``` js
mounted: function () {
this.$nextTick(function () {
// 代碼保證 this.$el 在 document 中
})
}
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>來找出所有使用此鉤子函數的示例。</p>
</div>
```
## `v-for`
### `v-for` 遍歷數組時的參數順序 <sup>變更</sup>
當包含 `index` 時,之前遍歷數組時的參數順序是 `(index, value)`。現在是 `(value, index)` ,來和 JavaScript 的原生數組方法 (例如 `forEach` 和 `map`) 保持一致。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>來找出那些使用舊有參數順序的示例。注意,如果你將你的 index 參數命名為一些不通用的名字 (例如 <code>position</code> 或 <code>num</code>),遷移工具將不會把它們標記出來。</p>
</div>
```
### `v-for` 遍歷對象時的參數順序 <sup>變更</sup>
當包含 `key` 時,之前遍歷對象的參數順序是 `(key, value)`。現在是 `(value, key)`,來和常見的對象迭代器 (例如 lodash) 保持一致。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>來找出那些使用舊有參數順序的示例。注意,如果你將你的 key 參數命名為一些不通用的名字 (例如 <code>name</code> 或 <code>property</code>),遷移工具將不會把它們標記出來。</p>
</div>
```
### `$index` and `$key` <sup>移除</sup>
已經移除了 `$index` 和 `$key` 這兩個隱式聲明變量,以便在 `v-for` 中顯式定義。這可以使沒有太多 Vue 開發經驗的開發者更好地閱讀代碼,并且在處理嵌套循環時也能產生更清晰的行為。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>來找出使用這些移除變量的示例。如果你沒有找到,也可以在<strong>控制臺錯誤</strong>中查找 (例如 <code>Uncaught ReferenceError: $index is not defined</code>)。</p>
</div>
```
### `track-by` <sup>替換</sup>
`track-by` 已經替換為 `key`,它的工作方式與其他屬性一樣,沒有 `v-bind` 或者 `:` 前綴,它會被作為一個字符串處理。多數情況下,你需要使用具有完整表達式的動態綁定 (dynamic binding) 來替換靜態的 key。例如,替換:
``` html
<div v-for="item in items" track-by="id">
```
你現在應該寫為:
``` html
<div v-for="item in items" v-bind:key="item.id">
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>來找出那些使用<code>track-by</code>的示例。</p>
</div>
```
### `v-for` 范圍值 <sup>變更</sup>
之前,`v-for="number in 10"` 的 `number` 從 0 開始到 9 結束,現在從 1 開始,到 10 結束。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>在代碼庫中使用正則 <code>/\w+ in \d+/</code>搜索。當出現在 <code>v-for</code> 中,請檢查是否受到影響。</p>
</div>
```
## Props
### `coerce` Prop 的參數 <sup>移除</sup>
如果需要檢查 prop 的值,創建一個內部的 computed 值,而不再在 props 內部去定義,例如:
``` js
props: {
username: {
type: String,
coerce: function (value) {
return value
.toLowerCase()
.replace(/\s+/, '-')
}
}
}
```
現在應該寫為:
``` js
props: {
username: String,
},
computed: {
normalizedUsername: function () {
return this.username
.toLowerCase()
.replace(/\s+/, '-')
}
}
```
這樣有一些好處:
- 你可以對保持原始 prop 值的操作權限。
- 通過給予驗證后的值一個不同的命名,強制開發者使用顯式申明。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找出包含 <code>coerce</code> 選項的實例。</p>
</div>
```
### `twoWay` Prop 的參數 <sup>移除</sup>
Props 現在只能單向傳遞。為了對父組件產生反向影響,子組件需要顯式地傳遞一個事件而不是依賴于隱式地雙向綁定。詳見:
- [自定義組件事件](components.html#自定義事件)
- [自定義輸入組件](components.html#使用自定義事件的表單輸入組件) (使用組件事件)
- [全局狀態管理](state-management.html)
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行 <a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>,找出含有 <code>twoWay</code> 參數的實例。</p>
</div>
```
### `v-bind` 的 `.once`和`.sync` 修飾符 <sup>移除</sup>
Props 現在只能單向傳遞。為了對父組件產生反向影響,子組件需要顯式地傳遞一個事件而不是依賴于隱式地雙向綁定。詳見:
- [自定義組件事件](components.html#自定義事件)
- [自定義輸入組件](components.html#使用自定義事件的表單輸入組件) (使用組件事件)
- [全局狀態管理](state-management.html)
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到使用 <code>.once</code> 和 <code>.sync</code> 修飾符的實例。</p>
</div>
```
### 修改 Props <sup>棄用</sup>
組件內修改 prop 是反模式 (不推薦的) 的。比如,先聲明一個 prop ,然后在組件中通過 `this.myProp = 'someOtherValue'` 改變 prop 的值。根據渲染機制,當父組件重新渲染時,子組件的內部 prop 值也將被覆蓋。
大多數情況下,改變 prop 值可以用以下選項替代:
- 通過 data 屬性,用 prop 去設置一個 data 屬性的默認值。
- 通過 computed 屬性。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行端對端測試,查看關于 prop 修改的<strong>控制臺警告信息</strong>。</p>
</div>
```
### 根實例的 Props <sup>替換</sup>
對于一個根實例來說 (比如:用 `new Vue({ ... })` 創建的實例),只能用 `propsData` 而不是 `props` 。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行端對端測試,將會彈出 <strong>failed tests</strong> 來通知你使用 <code>props</code> 的根實例已經失效。</p>
</div>
```
## 計算屬性
### `cache: false` <sup>棄用</sup>
在 Vue 未來的大版本中,計算屬性的緩存驗證將會被移除。把不緩存的計算屬性轉換為方法可以得到和之前相同的結果。
示例:
``` js
template: '<p>message: {{ timeMessage }}</p>',
computed: {
timeMessage: {
cache: false,
get: function () {
return Date.now() + this.message
}
}
}
```
或者使用組件方法:
``` js
template: '<p>message: {{ getTimeMessage() }}</p>',
methods: {
getTimeMessage: function () {
return Date.now() + this.message
}
}
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到 <code>cache: false</code> 的選項。</p>
</div>
```
## Built-In 指令
### `v-bind` 真/假值 <sup>變更</sup>
在2.0中使用 `v-bind` 時,只有 `null`, `undefined`,和 `false` 被看作是假。這意味著,`0` 和空字符串將被作為真值渲染。比如 `v-bind:draggable="''"` 將被渲染為 `draggable="true"`。
對于枚舉屬性,除了以上假值之外,字符串 `"false"` 也會被渲染為 `attr="false"`。
<p class="tip">注意,對于其它鉤子函數 (如 `v-if` 和 `v-show`),他們依然遵循 js 對真假值判斷的一般規則。</p>
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行端到端測試,如果你 app 的任何部分有可能被這個升級影響到,將會彈出<strong>failed tests</strong></p>
</div>
```
### 用 `v-on` 監聽原生事件 <sup>變更</sup>
現在在組件上使用 `v-on` 只會監聽自定義事件 (組件用 `$emit` 觸發的事件)。如果要監聽根元素的原生事件,可以使用 `.native` 修飾符,比如:
``` html
<my-component v-on:click.native="doSomething"></my-component>
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行端對端測試,如果你 app 的任何部分有可能被這個升級影響到,將會彈出<strong>failed tests</strong> </p>
</div>
```
### 帶有 `debounce` 的 `v-model`<sup>移除</sup>
Debouncing 曾經被用來控制 Ajax 請求及其它高耗任務的頻率。Vue 中`v-model`的 `debounce` 屬性參數使得在一些簡單情況下非常容易實現這種控制。但實際上,這是控制了**狀態更新**的頻率,而不是控制高耗時任務本身。這是個微小的差別,但是會隨著應用增長而顯現出局限性。
例如在設計一個搜索提示時的局限性:
```
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.js"></script>
<div id="debounce-search-demo" class="demo">
<input v-model="searchQuery" placeholder="Type something">
<strong>{{ searchIndicator }}</strong>
</div>
<script>
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: {
expensiveOperation: _.debounce(function () {
this.isCalculating = true
setTimeout(function () {
this.isCalculating = false
this.searchQueryIsDirty = false
}.bind(this), 1000)
}, 500)
}
})
</script>
```
使用 `debounce` 參數,便無法觀察 "Typing" 的狀態。因為無法對輸入狀態進行實時檢測。然而,通過將 `debounce` 與 Vue 解耦,可以僅僅只延遲我們想要控制的操作,從而避開這些局限性:
``` html
<!--
通過使用 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>
```
``` js
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 重構項目。
```
<div class="upgrade-path">
<h4>Upgrade Path</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找出使用 <code>debounce</code> 參數的 實例。</p>
</div>
```
### 使用 `lazy` 或者 `number` 參數的 `v-model` 。<sup>替換</sup>
`lazy` 和 `number` 參數現在以修飾符的形式使用,這樣看起來更加清晰,而不是這樣:
``` html
<input v-model="name" lazy>
<input v-model="age" type="number" number>
```
現在寫成這樣:
``` html
<input v-model.lazy="name">
<input v-model.number="age" type="number">
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行 <a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到這些棄用參數。</p>
</div>
```
### 使用內聯 `value`的`v-model` <sup>移除</sup>
`v-model` 不再以內聯 `value` 方式初始化的初值了,顯然他將以實例的 data 相應的屬性作為真正的初值。
這意味著以下元素:
``` html
<input v-model="text" value="foo">
```
在 data 選項中有下面寫法的:
``` js
data: {
text: 'bar'
}
```
將渲染 model 為 'bar' 而不是 'foo' 。同樣,對 `<textarea>` 已有的值來說:
``` html
<textarea v-model="text">
hello world
</textarea>
```
必須保證 `text` 初值為 "hello world"
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>升級后運行端對端測試,注意關于<code>v-model</code>內聯參數的 <strong>console warnings</strong></p>
</div>
```
### `v-model` with `v-for` Iterated Primitive Values <sup>移除</sup>
像這樣的寫法將失效:
``` html
<input v-for="str in strings" v-model="str">
```
因為 `<input>` 將被編譯成類似下面的 js 代碼:
``` js
strings.map(function (str) {
return createElement('input', ...)
})
```
這樣,`v-model` 的雙向綁定在這里就失效了。把 `str` 賦值給迭代器里的另一個值也沒有用,因為它僅僅是函數內部的一個變量。
替代方案是,你可以使用對象數組,這樣`v-model` 就可以同步更新對象里面的字段了,例如:
``` html
<input v-for="obj in objects" v-model="obj.str">
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行測試,如果你的 app 有地方被這個更新影響到的話將會彈出<strong>failed tests</strong>提示。</p>
</div>
```
### 帶有 `!important` 的`v-bind:style` <sup>移除</sup>
這樣寫將失效:
``` html
<p v-bind:style="{ color: myColor + ' !important' }">hello</p>
```
如果確實需要覆蓋其它的 `!important`,最好用字符串形式去寫:
``` html
<p v-bind:style="'color: ' + myColor + ' !important'">hello</p>
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行 <a href="https://github.com/vuejs/vue-migration-helper"> 遷移幫助工具。</a>找到含有 <code>!important</code> 的 style 綁定對象。</p>
</div>
```
### `v-el` 和`v-ref` <sup>替換</sup>
簡單起見,`v-el` 和 `v-ref` 合并為一個 `ref` 屬性了,可以在組件實例中通過 `$refs` 來調用。這意味著 `v-el:my-element` 將寫成這樣:`ref="myElement"`,`v-ref:my-component` 變成了這樣:`ref="myComponent"`。綁定在一般元素上時,`ref` 指 DOM 元素,綁定在組件上時,`ref` 為一組件實例。
因為 `v-ref` 不再是一個指令了而是一個特殊的屬性,它也可以被動態定義了。這樣在和`v-for` 結合的時候是很有用的:
``` html
<p v-for="item in items" v-bind:ref="'item' + item.id"></p>
```
以前 `v-el`/`v-ref` 和 `v-for` 一起使用將產生一個 DOM 數組或者組件數組,因為沒法給每個元素一個特定名字。現在你還仍然可以這樣做,給每個元素一個同樣的`ref`:
``` html
<p v-for="item in items" ref="items"></p>
```
和 1.x 中不同,`$refs` 不是響應的,因為它們在渲染過程中注冊/更新。只有監聽變化并重復渲染才能使它們響應。
另一方面,設計`$refs`主要是提供給 js 程序訪問的,并不建議在模板中過度依賴使用它。因為這意味著在實例之外去訪問實例狀態,違背了 Vue 數據驅動的思想。
```
<div class="upgrade-path">
<h4>升級方式</h4>
?<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找出實例中的 <code>v-el</code> 和 <code>v-ref</code> 。</p>
</div>
```
### `v-show`后面使用`v-else` <sup>移除</sup>
`v-else` 不能再跟在 `v-show`后面使用。請在`v-if`的否定分支中使用`v-show`來替代。例如:
``` html
<p v-if="foo">Foo</p>
<p v-else v-show="bar">Not foo, but bar</p>
```
現在應該寫出這樣:
``` html
<p v-if="foo">Foo</p>
<p v-if="!foo && bar">Not foo, but bar</p>
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找出實例中存在的 <code>v-else</code> 以及 <code>v-show</code>。</p>
</div>
```
## 自定義指令 <sup>簡化</sup>
在新版中,指令的使用范圍已經大大減小了:現在指令僅僅被用于低級的 DOM 操作。大多數情況下,最好是使用組件作為代碼復用的抽象層。
顯要的改變有如下幾點:
- 指令不再擁有實例。意思是,在指令的鉤子函數中不再擁有實例的 `this` 。替代的是,你可以在參數中接受你需要的任何數據。如果確實需要,可以通過 `el` 來訪問實例。
- 類似 `acceptStatement` ,`deep` ,`priority` 等都已被棄用。為了替換`雙向`指令,見 [示例](#雙向過濾器-替換)。
- 現在有些鉤子的意義和以前不一樣了,并且多了兩個鉤子函數。
幸運的是,新鉤子更加簡單,更加容易掌握。詳見 [自定義指令指南](custom-directive.html)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到定義指令的地方。在 helper 工具會把這些地方標記出來,因為很有可能這些地方需要重構。</p>
</div>
```
### 指令 `.literal` 修飾符 <sup>移除</sup>
`.literal` 修飾符已經被移除,為了獲取一樣的功能,可以簡單地提供字符串修飾符作為值。
示例,如下更改:
``` js
<p v-my-directive.literal="foo bar baz"></p>
```
只是:
``` html
<p v-my-directive="'foo bar baz'"></p>
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
?<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到實例中使用 `.literal` 修飾符的地方。</p>
</div>
```
## 過渡
### `transition` 參數 <sup>替換</sup>
Vue 的過渡系統有了徹底的改變,現在通過使用 `<transition>` 和 `<transition-group>` 來包裹元素實現過渡效果,而不再使用 `transition` 屬性。詳見 [Transitions guide](transitions.html)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到使用 <code>transition</code> 屬性的地方。</p>
</div>
```
### 可復用的過渡 `Vue.transition` <sup>替換</sup>
在新的過渡系統中,可以[通過模板復用過渡效果](transitions.html#Reusable-Transitions)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到使用 <code>transition</code> 屬性的地方。</p>
</div>
```
### 過渡的 `stagger` 參數 <sup>移除</sup>
如果希望在列表渲染中使用漸近過渡,可以通過設置元素的 `data-index` (或類似屬性) 來控制時間。請參考[這個例子](transitions.html#列表的漸進過渡)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到使用 <code>transition</code> 屬性的地方。升級期間,你可以“過渡”到新的過渡策略。</p>
</div>
```
## 事件
### `events` 選項 <sup>移除</sup>
`events` 選項被棄用。事件處理器現在在 `created` 鉤子中被注冊。參考詳細示例 [`$dispatch` and `$broadcast` 遷移指南](#dispatch-和-broadcast-替換)
### `Vue.directive('on').keyCodes` <sup>替換</sup>
新的簡明配置 `keyCodes` 的方式是通過 `Vue.config.keyCodes`例如:
``` js
// v-on:keyup.f1 不可用
Vue.config.keyCodes.f1 = 112
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到過時的 <code>keyCode</code> 配置</p>
</div>
```
### `$dispatch` 和 `$broadcast` <sup>替換</sup>
`$dispatch` 和 `$broadcast` 已經被棄用。請使用更多簡明清晰的組件間通信和更好的狀態管理方案,如:[Vuex](https://github.com/vuejs/vuex)。
因為基于組件樹結構的事件流方式實在是讓人難以理解,并且在組件結構擴展的過程中會變得越來越脆弱。這種事件方式確實不太好,我們也不希望在以后讓開發者們太痛苦。并且`$dispatch` 和 `$broadcast` 也沒有解決兄弟組件間的通信問題。
對于`$dispatch` 和 `$broadcast`最簡單的升級方式就是:通過使用事件中心,允許組件自由交流,無論組件處于組件樹的哪一層。由于 Vue 實例實現了一個事件分發接口,你可以通過實例化一個空的 Vue 實例來實現這個目的。
這些方法的最常見用途之一是父子組件的相互通信。在這些情況下,你可以使用 [`v-on`監聽子組件上 $emit 的變化](components.html#使用自定義事件的表單輸入組件)。這可以允許你很方便的添加事件顯性。
然而,如果是跨多層父子組件通信的話,`$emit` 并沒有什么用。相反,用集中式的事件中間件可以做到簡單的升級。這會讓組件之間的通信非常順利,即使是兄弟組件。因為 Vue 通過事件發射器接口執行實例,實際上你可以使用一個空的 Vue 實例。
比如,假設我們有個 todo 的應用結構如下:
```
Todos
├─ NewTodoInput
└─ Todo
└─ DeleteTodoButton
```
可以通過單獨的事件中心管理組件間的通信:
``` js
// 將在各處使用該事件中心
// 組件通過它來通信
var eventHub = new Vue()
```
然后在組件中,可以使用 `$emit`, `$on`, `$off` 分別來分發、監聽、取消監聽事件:
``` js
// NewTodoInput
// ...
methods: {
addTodo: function () {
eventHub.$emit('add-todo', { text: this.newTodoText })
this.newTodoText = ''
}
}
```
``` js
// DeleteTodoButton
// ...
methods: {
deleteTodo: function (id) {
eventHub.$emit('delete-todo', id)
}
}
```
``` js
// 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](https://github.com/vuejs/vuex)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找出使用 <code>$dispatch</code> 和 <code>$broadcast</code>的實例。</p>
</div>
```
## 過濾器
### 插入文本之外的過濾器 <sup>移除</sup>
現在過濾器只能用在插入文本中 (````{{ }}```` tags)。我們發現在指令 (如:`v-model`,`v-on`等) 中使用過濾器使事情變得更復雜。像`v-for` 這樣的列表過濾器最好把處理邏輯作為一個計算屬性放在 js 里面,這樣就可以在整個模板中復用。
總之,能在原生 js 中實現的東西,我們盡量避免引入一個新的符號去重復處理同樣的問題。下面是如何替換 Vue 內置過濾器:
#### 替換 `debounce` 過濾器
不再這樣寫
``` html
<input v-on:keyup="doStuff | debounce 500">
```
``` js
methods: {
doStuff: function () {
// ...
}
}
```
請使用 [lodash's `debounce`](https://lodash.com/docs/4.15.0#debounce) (也有可能是 [`throttle`](https://lodash.com/docs/4.15.0#throttle)) 來直接控制高耗任務。可以這樣來實現上面的功能:
``` html
<input v-on:keyup="doStuff">
```
``` js
methods: {
doStuff: _.debounce(function () {
// ...
}, 500)
}
```
這種寫法的更多優點詳見:[`v-model` 示例](#帶有-debounce-的-v-model 移除)。
#### 替換 `limitBy` 過濾器
不再這樣寫:
``` html
<p v-for="item in items | limitBy 10">{{ item }}</p>
```
在 computed 屬性中使用 js 內置方法:[`.slice` method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice#Examples):
``` html
<p v-for="item in filteredItems">{{ item }}</p>
```
``` js
computed: {
filteredItems: function () {
return this.items.slice(0, 10)
}
}
```
#### 替換 `filterBy` 過濾器
不再這樣寫:
``` html
<p v-for="user in users | filterBy searchQuery in 'name'">{{ user.name }}</p>
```
在 computed 屬性中使用 js 內置方法 [`.filter` method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Examples):
``` html
<p v-for="user in filteredUsers">{{ user.name }}</p>
```
``` js
computed: {
filteredUsers: function () {
var self = this
return self.users.filter(function (user) {
return user.name.indexOf(self.searchQuery) !== -1
})
}
}
```
js 原生的 `.filter` 同樣能實現很多復雜的過濾器操作,因為可以在計算 computed 屬性中使用所有 js 方法。比如,想要通過匹配用戶名字和電子郵箱地址 (不區分大小寫) 找到用戶:
``` 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` 過濾器
不這樣寫:
``` html
<p v-for="user in users | orderBy 'name'">{{ user.name }}</p>
```
而是在 computed 屬性中使用 [lodash's `orderBy`](https://lodash.com/docs/4.15.0#orderBy) (或者可能是 [`sortBy`](https://lodash.com/docs/4.15.0#sortBy)):
``` html
<p v-for="user in orderedUsers">{{ user.name }}</p>
```
``` js
computed: {
orderedUsers: function () {
return _.orderBy(this.users, 'name')
}
}
```
甚至可以字段排序:
``` js
_.orderBy(this.users, ['name', 'last_login'], ['asc', 'desc'])
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
?<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到指令中使用的過濾器。如果有些沒找到,看看<strong>控制臺錯誤信息</strong>。</p>
</div>
```
### 過濾器參數符號 <sup>變更</sup>
現在過濾器參數形式可以更好地與 js 函數調用方式一致,因此不用再用空格分隔參數:
``` html
<p>{{ date | formatDate 'YY-MM-DD' timeZone }}</p>
```
現在用圓括號括起來并用逗號分隔:
``` html
<p>{{ date | formatDate('YY-MM-DD', timeZone) }}</p>
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
?<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到老式的調用符號,如果有遺漏,請看<strong>控制臺錯誤信息</strong>。</p>
</div>
```
### 內置文本過濾器 <sup>移除</sup>
盡管插入文本內部的過濾器依然有效,但是所有內置過濾器已經移除了。取代的是,推薦在每個區域使用更專業的庫來解決。(比如用 [`date-fns`](https://date-fns.org/) 來格式化日期,用 [`accounting`](https://openexchangerates.github.io/accounting.js/) 來格式化貨幣)。
對于每個內置過濾器,我們大概總結了下該怎么替換。代碼示例可能寫在自定義 helper 函數,方法或計算屬性中。
#### 替換 `json` 過濾器
不用一個個改,因為 Vue 已經幫你自動格式化好了,無論是字符串,數字還是數組,對象。如果想用 js 的 `JSON.stringify` 功能去實現,你也可以把它寫在方法或者計算屬性里面。
#### 替換 `capitalize` 過濾器
``` js
text[0].toUpperCase() + text.slice(1)
```
#### 替換 `uppercase` 過濾器
``` js
text.toUpperCase()
```
#### 替換 `lowercase` 過濾器
``` js
text.toLowerCase()
```
#### 替換 `pluralize` 過濾器
NPM 上的 [pluralize](https://www.npmjs.com/package/pluralize) 庫可以很好的實現這個功能。如果僅僅想將特定的詞格式化成復數形式或者想給特定的值 ('0') 指定特定的輸出,也可以很容易地自定義復數格式化過濾器:
``` js
function pluralizeKnife (count) {
if (count === 0) {
return 'no knives'
} else if (count === 1) {
return '1 knife'
} else {
return count + 'knives'
}
}
```
#### Replacing the `currency` Filter
對于簡單的問題,可以這樣做:
``` js
'$' + price.toFixed(2)
```
大多數情況下,仍然會有奇怪的現象 (比如 `0.035.toFixed(2)` 向上取舍得到 `0.04`,但是 `0.045` 向下取舍卻也得到 `0.04`)。解決這些問題可以使用 [`accounting`](https://openexchangerates.github.io/accounting.js/) 庫來實現更多可靠的貨幣格式化。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到舍棄的過濾器。如果有些遺漏,請參考<strong>控制臺錯誤信息</strong>。</p>
</div>
```
### 雙向過濾器 <sup>替換</sup>
有些用戶已經樂于通過 `v-model` 使用雙向過濾器,以很少的代碼創建有趣的輸入。盡管表面上很*簡單*,雙向過濾器也會暗藏一些巨大的復雜性——甚至促使狀態更新變得遲鈍影響用戶體驗。推薦用包裹一個輸入的組件取而代之,這樣以更顯性且功能更豐富的方式創建自定義的輸入。
我們現在做一次雙向匯率過濾器的遷移作為示范:
<iframe width="100%" height="300" src="https://jsfiddle.net/chrisvfritz/6744xnjk/embedded/js,html,result" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
它基本工作良好,但是拖延的狀態更新會導致奇怪的行為。比如,點擊 `Result` 標簽,試著在其中一個輸入框中輸入 `9.999`。當輸入框失去焦點的時候,其值將會更新到 `$10.00`。然而當我們從整個計算器的角度看時,你會發現存儲的數據是 `9.999`。用戶看到的已經不是真實的同步了!
為了過渡到一個更加健壯的 Vue 2.0 的方案,讓我們首先在一個新的 `<currency-input>` 組件中包裹這個過濾器:
<iframe width="100%" height="300" src="https://jsfiddle.net/chrisvfritz/943zfbsh/embedded/js,html,result" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
它允許我們添加獨立過濾器無法封裝的行為,比如選擇輸入框聚焦的內容。下一步我們從過濾器中提取業務邏輯。接下來是我們把所有的東西放到一個外部的 [`currencyValidator` 對象](https://gist.github.com/chrisvfritz/5f0a639590d6e648933416f90ba7ae4e)中:
<iframe width="100%" height="300" src="https://jsfiddle.net/chrisvfritz/9c32kev2/embedded/js,html,result" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
這會更加模塊化,不只是更容易的遷移到 Vue 2,同時也允許匯率間隙和格式化:
- 從你的 Vue 代碼中獨立出來進行單元測試
- 在你的應用程序的別的部分中使用,比如驗證驗證一個 API 端的負荷
把這個驗證器提取出來之后,我們也可以更舒適的把它構建到更健壯的解決方案中。那些古怪的狀態也消除了,用戶不再可能會輸入錯誤,就像瀏覽器原生的數字輸入框一樣。
然而在 Vue 1.0 的過濾器中,我們仍然是受限的,所以還是完全升級到 Vue 2.0 吧:
<iframe width="100%" height="300" src="https://jsfiddle.net/chrisvfritz/1oqjojjx/embedded/js,html,result" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
你可能注意到了:
- 我們的輸入框的各方面都更顯性,使用生命周期鉤子和 DOM 事件以替代雙向過濾器的隱藏行為。
- 我們現在可以在自定義輸入框中直接使用 `v-model`,其不只是固定配合正常的輸入框來使用,這也意味著我們的組件是對 Vuex 友好的。
- 因為我們已經不再要求過濾器選項必須要有一個返回值,所以實際上我們的匯率工作可以異步完成。這意味著如果我們有很多應用需要和匯率打交道,我們可以輕松的提煉這個邏輯并成為一個共享的微服務。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到在例如 <code>v-model</code> 的指令中使用過濾器的例子。如果你錯過了,則應該會收到<strong>命令行報錯</strong>。</p>
</div>
```
## 插槽
### 重名的插槽 <sup>移除</sup>
同一模板中的重名 `<slot>` 已經棄用。當一個插槽已經被渲染過了,那么就不能在同一模板其它地方被再次渲染了。如果要在不同位置渲染同一內容,可以用 prop 來傳遞。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>更新后運行測試,查看<strong>控制臺警告信息</strong> 關于重名 slots 的提示 <code>v-model</code>。</p>
</div>
```
### `slot` 樣式參數 <sup>移除</sup>
通過具名 `<slot>` 插入的片段不再保持 `slot` 的參數。請用一個包裹元素來控制樣式。或者用更高級方法:通過編程方式修改內容 :[render functions](render-function.html)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
?<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到選擇 slots 標簽 CSS 選擇器 (例如:<code>[slot="my-slot-name"]</code>)。</p>
</div>
```
## 特殊屬性
### `keep-alive` 屬性 <sup>替換</sup>
`keep-alive` 不再是一個特殊屬性而是一個包裹組件,類似于 `<transition>`比如:
``` html
<keep-alive>
<component v-bind:is="view"></component>
</keep-alive>
```
這樣可以在含多種狀態子組件中使用 `<keep-alive>` :
``` html
<keep-alive>
<todo-list v-if="todos.length > 0"></todo-list>
<no-todos-gif v-else></no-todos-gif>
</keep-alive>
```
<p class="tip">當 `<keep-alive>` 含有不同子組件時,應該分別影響到每一個子組件。不僅是第一個而是所有的子組件都將被忽略。</p>
和 `<transition>`一起使用時,確保把內容包裹在內:
``` html
<transition>
<keep-alive>
<component v-bind:is="view"></component>
</keep-alive>
</transition>
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到<code>keep-alive</code> 屬性。</p>
</div>
```
## 計算插值
### 屬性內部的計算插值 <sup>移除</sup>
屬性內部的計算插值已經不能再使用了:
``` html
<button class="btn btn-{{ size }}"></button>
```
應該寫成行內表達式:
``` html
<button v-bind:class="'btn btn-' + size"></button>
```
或者計算屬性:
``` html
<button v-bind:class="buttonClasses"></button>
```
``` js
computed: {
buttonClasses: function () {
return 'btn btn-' + size
}
}
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到屬性內部的計算插值</p>
</div>
```
### HTML 計算插值 <sup>移除</sup>
HTML 的計算插值 (````{{{ foo }}}````) 已經移除,取代的是 [`v-html` 指令](../api/#v-html)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到 HTML 計算插值。</p>
</div>
```
### 單次綁定<sup>替換</sup>
單次綁定 (````{{* foo }}````) 已經被新的 [`v-once` directive](../api/#v-once) 取代。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行 <a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到單次綁定使用位置。</p>
</div>
```
## 響應
### `vm.$watch` <sup>changed</sup>
通過 `vm.$watch`創建的觀察器現在將在組件渲染時被激活。這樣可以讓你在組件渲染前更新狀態,不用做不必要的更新。比如可以通過觀察組件的 prop 變化來更新組件本身的值。
如果以前通過 `vm.$watch` 在組件更新后與 DOM 交互,現在就可以通過`updated`生命周期鉤子來做這些。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行測試,如果有依賴于老方法的觀察器將彈出 <strong>failed tests</strong>。</p>
</div>
```
### `vm.$set` <sup>變更</sup>
`vm.$set` 只是 [`Vue.set`](../api/#Vue-set) 的別名。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到過時的用法</p>
</div>
```
### `vm.$delete` <sup>變更</sup>
`vm.$delete` 現在只是:[`Vue.delete`](../api/#Vue-delete) 別名。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到過時的用法</p>
</div>
```
### `Array.prototype.$set` <sup>棄用</sup>
用 `Vue.set` 替代
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到數組上的<code>.$set</code>。如有遺漏請參考<strong>控制臺錯誤信息</strong>。</p>
</div>
```
### `Array.prototype.$remove` <sup>移除</sup>
用 `Array.prototype.splice` 替代,例如:
``` js
methods: {
removeTodo: function (todo) {
var index = this.todos.indexOf(todo)
this.todos.splice(index, 1)
}
}
```
或者更好的方法,直接給除去的方法一個 index 參數:
``` js
methods: {
removeTodo: function (index) {
this.todos.splice(index, 1)
}
}
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到數組上的<code>.$remove</code>。如有遺漏請參考<strong>控制臺錯誤信息</strong></p>
</div>
```
### Vue 實例上的`Vue.set` 和 `Vue.delete`<sup>移除</sup>
`Vue.set` 和 `Vue.delete` 在實例上將不再起作用。現在都強制在實例的 data 選項中聲明所有頂級響應值。如果刪除實例屬性或實例`$data`上的某個值,直接將它設置為 null 即可。
```
<div class="upgrade-path">
<h4>升級方式</h4>
?<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到實例中的 <code>Vue.set</code> 或 <code>Vue.delete</code> 。如有遺漏請參考<strong>控制臺錯誤信息</strong>。</p>
</div>
```
### 替換 `vm.$data` <sup>移除</sup>
現在禁止替換實例的 $data。這樣防止了響應系統的一些極端情況并且讓組件狀態更加可控可預測 (特別是對于存在類型檢查的系統)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到覆蓋 <code>vm.$data</code>的位置。如有遺漏請參考<strong>控制臺警告信息</strong>。</p>
</div>
```
### `vm.$get` <sup>移除</sup>
可以直接取回響應數據。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行 <a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到 <code>vm.$get</code> 的位置。如有遺漏請參考 <strong>控制臺錯誤信息</strong>。</p>
</div>
```
## 圍繞 DOM 的實例方法
### `vm.$appendTo` <sup>移除</sup>
使用 DOM 原生方法:
``` js
myElement.appendChild(vm.$el)
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到 <code>vm.$appendTo</code> 的位置。如果有遺漏可以參考<strong>控制臺錯誤信息</strong>。</p>
</div>
```
### `vm.$before` <sup>移除</sup>
使用 DOM 原生方法:
``` js
myElement.parentNode.insertBefore(vm.$el, myElement)
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行 <a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到 <code>vm.$before</code>。如有遺漏,請參考 <strong>控制臺錯誤信息</strong>。</p>
</div>
```
### `vm.$after` <sup>移除</sup>
使用 DOM 原生方法:
``` js
myElement.parentNode.insertBefore(vm.$el, myElement.nextSibling)
```
如果 `myElement` 是最后一個節點也可以這樣寫:
``` js
myElement.parentNode.appendChild(vm.$el)
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
?<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到 <code>vm.$after</code> 的位置。如有遺漏,請參考<strong>控制臺錯誤信息</strong>。</p>
</div>
```
### `vm.$remove` <sup>移除</sup>
使用 DOM 原生方法:
``` js
vm.$el.remove()
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行 <a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到<code>vm.$remove</code>。如有遺漏,請參考<strong>控制臺錯誤信息</strong>。</p>
</div>
```
## 底層實例方法
### `vm.$eval` <sup>移除</sup>
盡量不要使用,如果必須使用該功能并且不肯定如何使用請參考 [the forum](https://forum.vuejs.org/)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
?<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到使用 <code>vm.$eval</code> 的位置。如有遺漏請參考<strong>控制臺錯誤信息</strong>。</p>
</div>
```
### `vm.$interpolate` <sup>移除</sup>
盡量不要使用,如果必須使用該功能并且不肯定如何使用請參考 [the forum](https://forum.vuejs.org/)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到<code>vm.$interpolate</code>。如有遺漏請參考<strong>控制臺錯誤信息</strong>.</p>
</div>
```
### `vm.$log` <sup>移除</sup>
請使用 [Vue Devtools](https://github.com/vuejs/vue-devtools) 感受最佳 debug 體驗。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到 <code>vm.$log</code>。如有遺漏請參考<strong>控制臺錯誤信息</strong>.</p>
</div>
```
## 實例 DOM 選項
### `replace: false` <sup>移除</sup>
現在組件總是會替換掉他們被綁定的元素。為了模仿`replace: false`的行為,可以用一個和將要替換元素類似的元素將根組件包裹起來:
``` js
new Vue({
el: '#app',
template: '<div id="app"> ... </div>'
})
```
或者使用渲染函數:
``` js
new Vue({
el: '#app',
render: function (h) {
h('div', {
attrs: {
id: 'app',
}
}, /* ... */)
}
})
```
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到 <code>replace: false</code>使用的位置。</p>
</div>
```
## 全局配置
### `Vue.config.debug` <sup>移除</sup>
不再需要,因為警告信息將默認在堆棧信息里輸出。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到包含<code>Vue.config.debug</code>的地方。</p>
</div>
```
### `Vue.config.async` <sup>移除</sup>
異步操作現在需要渲染性能的支持。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行 <a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到使用<code>Vue.config.async</code>的實例。</p>
</div>
```
### `Vue.config.delimiters` <sup>替換</sup>
以[模板選項](../api/#delimiters)的方式使用。這樣可以在使用自定義分隔符時避免影響第三方模板。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到使用<code>Vue.config.delimiters</code>的實例。</p>
</div>
```
### `Vue.config.unsafeDelimiters` <sup>移除</sup>
HTML 插值[替換為 `v-html`](#HTML-計算插值-移除)。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到 <code>Vue.config.unsafeDelimiters</code>。然后 helper 工具也會找到 HTML 插入的實例,可以用`v-html`來替換。</p>
</div>
```
## 全局 API
### 帶 `el` 的 `Vue.extend` <sup>移除</sup>
el 選項不再在 `Vue.extend`中使用。僅在實例創建參數中可用。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>更新后運行測試在<strong>控制臺警告信息</strong>中找到關于帶有<code>Vue.extend</code>的<code>el</code>。</p>
</div>
```
### `Vue.elementDirective` <sup>移除</sup>
用組件來替代
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到包含<code>Vue.elementDirective</code>的實例。</p>
</div>
```
### `Vue.partial` <sup>移除</sup>
Partials 已被移除,取而代之的是更明確的組件之間的數據流--props。除非你正在使用一個部分性能關鍵型區域,否則建議只使用一個 [normal component](components.html) 來代替。如果你是動態綁定部分的 `name`,您可以使用 [dynamic component](components.html#動態組件)。
如果你碰巧在你的應用程序的性能關鍵部分使用 partials,那么你應該升級到[函數式組件](render-function.html#函數式組件)。它們必須在純 JS / JSX 文件中 (而不是在 `.vue` 文件中),并且是無狀態的和無實例的,就像 partials。這使得渲染極快。
函數式組件相對于 partials 一個好處是它們可以更具動態性,因為它們允許您訪問 JavaScript 的全部功能。然而,這是有成本的。如果你從來沒有使用過渲染式的組件框架,你可能需要花費更長的時間來學習它們。
```
<div class="upgrade-path">
<h4>升級方式</h4>
<p>運行<a href="https://github.com/vuejs/vue-migration-helper">遷移工具</a>找到包含 <code>Vue.partial</code>的實例</p>
</div>
```
- 寫在前面
- 基礎
- 安裝
- 介紹
- Vue實例
- 模板語法
- 計算屬性和偵聽器
- Class 與 Style 綁定
- 條件渲染
- 列表渲染
- 事件處理
- 表單輸入綁定
- 組件基礎
- 深入了解組件
- 組件注冊
- Prop
- 自定義事件
- 插槽
- 動態組件 & 異步組件
- 處理邊界情況
- 過渡 & 動畫
- 進入/離開 & 列表過渡
- 狀態過渡
- 可復用性 & 組合
- 混入
- 自定義指令
- 渲染函數 & JSX
- 插件
- 過濾器
- 工具
- 生產環境部署
- 單文件組件
- 單元測試
- TypeScript 支持
- 規模化
- 路由
- 狀態管理
- 服務端渲染
- 內在
- 深入響應式原理
- 遷移
- 從 Vue 1.x 遷移
- 從 Vue Router 0.7.x 遷移
- 從 Vuex 0.6.x 遷移到 1.0
- 更多
- 對比其他框架
- 加入 Vue.js 社區
- 開發團隊