1.$refs 的使用
- 父组件使用
this.$refs.父组件ref名称,获取原生DOM对象 - 父组件可以通过
this.$refs.子组件ref名称,获取到子组件对象,也可以访问子组件对象身上的属性和方法
App.vue
<template>
<div>
<h1>1.$refs是使用</h1>
<!-- 给自己标签添加 ref 属性 -->
<p ref="pRef" id="cuteP">我是可爱的p</p>
<!-- 给子组件添加 ref 属性 -->
<Demo ref="demoRef"></Demo>
</div>
</template>
<script>
// 引入子组件
import Demo from "@/components/Demo.vue"
export default {
// 注册子组件
components: {
Demo
},
mounted(){
const p=document.getElementById('cuteP')
console.log(p,111)
console.log(this.$refs.pRef,222)
console.log(this.$refs.demoRef.msg,333)
this.$refs.demoRef.fn()
console.log(this.$refs.demoRef,444)
}
}
</script>
src/components/Demo.vue(子组件)
<template>
<div>我是 Demo 子组件</div>
</template>
<script>
export default {
data() {
return {
msg: "我是 Demo 子组件中的 msg"
}
},
mounted() {
console.log(this,'我是 Demo 子组件中的 this')
},
methods: {
fn() {
console.log("我是 Demo 子组件中的 fn 方法")
}
}
}
</script>
2. $nextTick 的使用
App.vue
<template>
<div>
<h1>2. $nextTick 的使用</h1>
<h4 ref="h4Ref">{{ msg }}</h4>
<button @click="changeMsg">点我修改 h4 的内容</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: "我是一个小小的 h4"
}
},
methods: {
changeMsg() {
this.msg = "我是一个大大的 h4"
console.log(this.msg, 111)
console.log(this.$refs.h4Ref.innerHTML, 222)
this.$nextTick(() => {
console.log(this.$refs.h4Ref.innerHTML, 333)
})
}
},
updated() {
console.log(this.$refs.h4Ref.innerHTML,444)
}
}
</script>
- 打印111,因为数据修改后更新 DOM 是异步操作(数据修改了)
- 打印222,DOM 还未更新
- 打印333,等待下一次 DOM 更新完毕后执行(
this.$nextTick()) - 打印444,会让业务逻辑产生割裂, 可读性不高
3. $nextTick 的应用场景
需求: 点击按钮, 让文本框显示并获取焦点 App.vue
<template>
<div>
<h1>3. $nextTick 的应用场景</h1>
<input ref="inpRef" v-if="isShow" type="text">
<button v-else @click="showSearch">点我显示搜索框</button>
</div>
</template>
<script>
export default {
data() {
return {
isShow: false,
}
},
methods: {
async showSearch() {
this.isShow = true
//◆法1
this.$nextTick(() => {
this.$refs.inpRef.focus()
})
console.log(this.$nextTick())//Promise
//◆法2
// this.$nextTick().then(() => {
// this.$refs.inpRef.focus()
// })
//◆法3
// await this.$nextTick()
// this.$refs.inpRef.focus()
}
}
}
</script>
4、v-model的原理
- 1.父向子传值,子组件收到值后,使用插值表达式渲染在页面上
- 2.当子组件中的按钮被点击,触发点击事件,触发父组件的 input 事件,传递最新的值给父组件
- 3.父组件收到最新的值后,重新给
count赋值,count修改了,传递给子组件的value也会更新
App.vue
<template>
<div>
<h1>4. v-model 的本质</h1>
<AddBtn :value="count" @input="(val) => count = val"></AddBtn>
</div>
</template>
<script>
//引入子组件
import AddBtn from '@/components/AddBtn.vue'
export default {
//注册子组件
components:{
AddBtn
},
data() {
return {
count: 10
}
}
}
</script>
src/components/AddBtn.vue(子组件)
<template>
<div>
<p>子组件库存: {{ value }}</p>
<button @click="addFn">增加+1</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number,
default: 0
}
},
methods: {
addFn () {
this.$emit('input', this.value + 1)
}
}
}
</script>
总结:
v-model本质上是一个语法糖- 给元素绑定
value属性 - 给元素绑定
input事件,在事件处理函数中修改绑定的数据