第一次使用vue3遇到的问题

文章讲述了在Vue.js中如何通过计算属性实现props的双向绑定以及在使用v-if时遇到的ref获取DOM节点问题。当试图修改props的值时,应通过自定义事件通知父组件进行修改。同时,由于v-if导致的DOM延迟渲染,单纯使用nextTick无法解决ref获取输入框的问题,最终通过querySelector解决。
摘要由CSDN通过智能技术生成

通过修改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来重新获取该节点,成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值