一、獲取DOM元素
在Vue中獲取DOM元素,我們可以用ref
。
用法(和React一樣):
(1)在組件的DOM部分,任意標籤中 寫上:ref="xxx"
(2)通過組件對象 this.$refs.xxx
獲取到元素
1、獲取HTML標籤的DOM
例1:
<div id="app"></div>
<script type="text/javascript">
let App = {
template: `
<div>
<button ref="btn">我是按鈕</button>
</div>`,
beforeCreate() {
//這裏不能操作數據
console.log('beforeCreate: ', this.$refs.btn);
},
created() {
//這裏可以操作數據了
console.log('created: ', this.$refs.btn);
},
beforeMount() {
//new Vue 發生裝載, 替換 <div id="app">之前
console.log('beforeMount: ', this.$refs.btn);
},
mounted() {
//裝在數據之後
console.log('mounted: ', this.$refs.btn);
},
};
new Vue({
el: '#app',
components: {
app: App
},
template: `<app />`,
});
</script>
控制檯輸出:
說明:mounted()時才能獲取this.$refs.btn
2、獲取組件的DOM
例2:
<div id="app"></div>
<script type="text/javascript">
let Temp = {
template: `
<div>我是子組件</div>
`,
};
let App = {
components: {
temp: Temp,
},
template: `<temp ref="tmp"/>`,
mounted() {
console.log(this.$refs.tmp);
},
};
let vm = new Vue({
el: '#app',
components: {
app: App
},
template: `<app />`,
});
</script>
控制檯輸出:
我們看到控制檯輸出
的是
temp組件
。
這裏我們要關注的是 組件的 各個屬性(eg: $ el、$ parent 等)···
假如我們把console.log(this.$refs.tmp)改爲:
console.log(this.$refs.tmp.$el);
控制檯會輸出下圖,由此可知 $el 代表着什麼~
總結:
- $parent: 獲取當前組件的父組件
- $children:················ 的子組件
- $root:獲取new Vue的實例 (即上面的:vm)
- $el: 獲取當前組件的DOM元素
二、給DOM元素添加事件的特殊情況
例:
要求:在顯示input元素的瞬間,獲取input的焦點
<div id="app"></div>
<script type="text/javascript">
let App = {
template: `
<div>
<input type="text" v-if="isShow" ref="myInput" />
</div>`,
data() {
return {
isShow: false,
};
},
mounted() {
this.isShow = true; //顯示input元素
this.$refs.myInput.focus(); //獲取input的焦點
},
};
let vm = new Vue({
el: '#app',
components: {
app: App
},
template: `<app />`,
});
</script>
運行後報錯:
報錯顯示focus不存在,原因是 this.$refs.myInput
也是undefined,爲什麼ref沒獲取到DOM元素呢?
我們先思考,如果我們把mounted函數內改成:
mounted() {
this.isShow = true;
this.isShow = false;
this.isShow = true;
},
運行過程中,input元素會 先顯示,再消失,然後再顯示嗎?
答案是否定的。因爲Vue會先讓代碼執行完,然後纔會根據最終的值,進行DOM操作。
其實上面的代碼等同於下面的代碼:
mounted() {
this.isShow = true;
},
那麼怎麼解決呢?
這裏我們用 $nextTick
解決~
vm.$nextTick
什麼時候用:在Vue渲染DOM到頁面後 立即做某件事,用$nextTick
this.$nextTick(function() {
·····dosomething
})
修改版:
let App = {
template: `
<div>
<input type="text" v-if="isShow" ref="myInput" />
</div>`,
data() {
return {
isShow: false,
};
},
mounted() {
//顯示input元素的瞬間,獲取焦點
this.isShow = true;
this.$nextTick(function() {
this.$refs.myInput.focus();
});
},
};
let vm = new Vue({
el: '#app',
components: {
app: App
},
template: `<app />`,
});