處理邊界情況
All the features on this page document the handling of edge cases,meaning unusual situations that sometimes require bending Vue’s rules a little. Note however, that they all have disadvantages or situations where they could be dangerous.
特殊情況下的處理方式,有利有弊
1. 訪問元素&組件
1.1 訪問根實例(Accessing the Root Instance )
通過 this.$root
根實例
// The root Vue instance
new Vue({
data: {
foo: 1
},
created:function(){
// 【獲取根組件的數據】
console.log(this.$root.foo);
// 【寫入根組件的數據】
this.$root.foo = 2
// 【訪問根組件的計算屬性】
this.$root.bar;
},
computed: {
bar: function () {
alert('我是計算屬性bar,只要有人訪問我或者改變我的值,我就執行')
}
},
methods: {
baz: function () {
alert('baz')
}
}
})
這種適合小型代碼量時使用,中大型項目還是推薦用 Vuex
來管理應用的狀態:如下
用根實例獲取狀態 VS 用Vuex
管理狀態
完整代碼
1.2 訪問父組件實例
Similar to
$root
, the$parent
property can be used to access the parent instance from a child.
This can be tempting to reach for as a lazy alternative to passing data with a prop.
父組件通過prop向子組件傳值,子組件也可通過$parent訪問父組件的值
1.3 訪問子組件或子元素
通過$refs
訪問子組件,注意: $refs
只會在組件渲染完成之後生效。
<div id="app">
<base-input ref="usernameInput"></base-input>
</div>
<script>
Vue.component("base-input", {
template: "<input type='input' ref='input'>",
methods: {
popUp() {
alert(11)
},
focus: function () {
this.$refs.input.focus()
}
}
});
new Vue({
el: "#app",
data: {},
mounted: function () {
this.$refs.usernameInput.popUp();
this.$refs.usernameInput.focus();
}
});
</script>
1.4 依賴注入
In fact, you can think of dependency injection as sort of “long-range props”
使用props是父組件向子組件共享數據
而使用依賴注入是父組件向所有的子孫組件共享數據(可跨層級的分享數據)
使用方法:
// 父組件中拋出要分享的數據
provide: function () {
return {
getMap: this.getMap
}
}
// 在子組件中注入一下就可以用了,so easy!
inject: ['getMap']
2. 程序化的事件監聽(Programmatic Event Listeners )
- Listen for an event with
$on(eventName, eventHandler)
- Listen for an event only once with
$once(eventName, eventHandler)
- Stop listening for an event with
$off(eventName, eventHandler)
當你需要在一個組件實例上手動偵聽事件時,它們是派得上用場的
<div id="app">
<input ref="dateInput" v-model="date" type="text" />
</div>
<script>
new Vue({
el: "#app",
data: {
date: null
},
mounted: function() {
var picker = new Pikaday({
field: this.$refs.dateInput,
format: "YYYY-MM-DD"
});
this.$once("hook:beforeDestroy", function() {
picker.destroy();
});
}
});
</script>
3. 循環引用
3.1 遞歸組件
Components can recursively invoke themselves in their own template. However, they can only do so with the
name
option
組件可以在自身模板中調用自己,注意:不要陷入無限循環
<div id="app">
<base-input></base-input>
</div>
<script>
Vue.component("base-input", {
name: 'stack-overflow',
template: '<div><stack-overflow></stack-overflow></div>' // 無限循環:報錯:Maximum call stack size exceeded
});
new Vue({
el: "#app",
data: {}
});
</script>
3.2 組件之間的循環引用
常見場景:渲染多層級結構時會用到
4. 定義模板的另外兩種方式
4.1 Inline Template
這種方式會放模板的作用域容易混淆,不推薦,還是推薦用組件中的 template
選項或者.vue
文件中的元素
<my-component inline-template>
<div>
<p>These are compiled as the component's own template.</p>
<p>Not parent's transclusion content.</p>
</div>
</my-component>
4.2 X-Template
這個有點像mustuche
模板的用法
<script type="text/x-template" id="hello-world-template">
<p>Hello hello hello</p>
</script>
Vue.component('hello-world', {
template: '#hello-world-template'
})
5. 控制更新(Controlling Updates)
5.1 強制更新
If you find yourself needing to force an update in Vue, in 99.99% of cases, you’ve made a mistake somewhere.
使用 $forceUpdate
強制更新,注意:需要強制更新的情況極少,99%可能性是你哪邊出錯了
5.2 通過 v-once
創建低開銷的靜態組件
要渲染的靜態內容很多,明顯影響了渲染性能時可以用,一般不要用。
Vue.component('terms-of-service', {
template: `
<div v-once>
<h1>Terms of Service</h1>
... a lot of static content ...
</div>
`
})
更多Vue文檔解讀:《Vue Doc 筆記》