通过修改props中的值来直接修改父组件内属性的值
props内的值是只读的,不可以直接修改,如果要想修改的话需要通过自定义事件向父组件传参在父组件中修改达到双向绑定的效果,以下是一个例子,在封装对话框组件时需要双向绑定对话框中的dialog属性来达到控制对话框出现和隐藏的效果,此时可以利用计算属性来简化代码:
// 自定义事件向父组件传参
const $emit = defineEmits(['sendResetDialog')
// 定义props
const props = defineProps({
resetDialog: {
default: false,
type: Boolean
}
})
// 定义计算属性resetDialog
const resetDialog = computed({
get() {
return props.resetDialog
},
set(newValue) {
$emit('sendResetDialog', newValue)
}
})
如上,使用计算属性时拿计算属性的值会走get函数,拿到props中的resetDialog,当给计算属性赋值时会走set函数,set函数中存在参数newVal就是要给计算属性赋的值,在set函数中触发自定义事件在父组件内监听即可获得最新的resetDialog的值,之后赋值给父组件内的属性即可达到双向绑定直接修改props中属性的值
通过ref获取不到dom节点
<div class="card-header" @dblclick="appearTitleInput">
<span v-if="!titleFlag">{{ title }}</span>
<input v-else type="text" @blur="reTitle" class="title-input" ref="titleInputRef" v-model="title1" />
</div>
// 显示卡片标题的方法
const appearTitleInput = () => {
title1.value = title.value
titleFlag.value = true
// 获取输入框节点
const titleInputRef = ref(null)
titleInputRef.focus()
}
以上代码大概的预期要求就是有一个卡片标题,当双击标题时标题文字会消失之后出现一个输入框来修改标题内容,之后需要让输入框在出现时获取焦点,因此需要获取输入框的dom节点使用focus方法,但是没有效果,控制台打印之后发现titleInputRef为空,之后看代码发现使用了v-if,获取时输入框节点还没有渲染,之后加上nextTick,代码如下:
// 显示卡片标题的方法
const appearTitleInput = () => {
title1.value = title.value
titleFlag.value = true
nextTick(() => {
// 获取输入框节点
const titleInputRef = ref(null)
titleInputRef.focus()
})
}
用nextTick将获取节点延后到输入框节点渲染之后,之后发现还是不行,titleInputRef仍然为空,之后又用了setTimeout延时函数,仍然没有效果
最后查了不少资料,大概有了一个猜测,那就是ref获取节点的时间是在整体第一次渲染时,之后便不在获取,因此在第一次ref获取完后因为v-if的原因没有渲染,因此无法获取,后续便不在获取,因此nextTick之类的方法都没有用(以上为我自己查资料之后综合资料做的猜测,不敢保证是否正确,大家如果有知道的可以在评论里指正,谢谢),最后处理方法如下:
const appearTitleInput = () => {
title1.value = title.value
titleFlag.value = true
nextTick(() => {
// 获取输入框节点
const titleInputRef = document.querySelector('.title-input')
titleInputRef.focus()
})
}
使用原生js中的querySelector来重新获取该节点,成功