You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js 3中QuillJS编辑器清空内容时报错:Cannot read properties of null

Vue3选项式API中QuillJS清空编辑器报错的解决方法

问题场景

在Vue3选项式API项目中集成Quill编辑器后,提交表单调用handleSubmission方法时,尝试通过deleteText、setText或setContents清空编辑器内容,均触发如下错误:

Uncaught TypeError: Cannot read properties of null (reading 'offset')
    at quill.js?v=b3144345:12600:26
    at Array.map (<anonymous>)
    at Proxy.normalizedToRange (quill.js?v=b3144345:12597:31)
    at Proxy.getRange (quill.js?v=b3144345:12586:25)
    at Proxy.update (quill.js?v=b3144345:12723:43)
    at Proxy.update (quill.js?v=b3144345:13796:20)
    at Proxy.getSelection (quill.js?v=b3144345:13690:10)
    at Proxy.modify (quill.js?v=b3144345:13906:44)
    at Proxy.deleteText (quill.js?v=b3144345:13553:19)
    at Proxy.handleSubmission (AppChatContainer.vue:47:18)

组件核心代码如下:

<script>
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import Quill from 'quill'

export default {
  name: 'AppChatContainer',
  components: { FontAwesomeIcon },
  props: {
    messages: {
      type: Array,
      required: true,
      default: () => []
    },
    isSending: {
      type: Boolean,
      default: false
    }
  },
  emits: ['new-message'],
  data() {
    return {
      quill: null
    }
  },
  mounted() {
    this.quill = new Quill('#message', {
      theme: 'bubble',
      modules: {
        toolbar: [
          ['bold', 'italic', { color: [] }],
          [{ list: 'ordered' }, { list: 'bullet' }]
        ]
      }
    })
  },
  methods: {
    handleSubmission() {
      const message = this.quill.getContents()
      this.$emit('new-message', message)
      // 以下三种方式均报错
      // this.quill.setContents([{ insert: '\n' }])
      // this.quill.setText('');
      this.quill.deleteText(0, this.quill.getLength())
    },
    convertDeltaToHtml(delta) {
      const tempQuill = new Quill(document.createElement('div'))
      tempQuill.setContents(delta)
      return tempQuill.root.innerHTML
    }
  }
}
</script>

<template>
  <form class="h-100 position-relative" @submit.prevent="handleSubmission">
    <div class="flex-grow-1 overflow-y-scroll">
      <div
        v-for="message in messages"
        :key="message.id"
        :class="`message mb-4 ${message.isAuthor ? 'author' : ''} ${message.isSending ? 'sending' : ''}`"
      >
        <div class="content" v-html="convertDeltaToHtml(message.content)" />
        <small v-if="message.isSending" class="text-gray-700 fw-light d-block mt-1 ms-2 me-3">
          Envois en cours...
        </small>
        <small v-else class="text-gray-700 fw-light d-block mt-1 ms-2 me-3">
          {{ message.isAuthor ? 'Vous' : message.authorName }}, le {{ message.date }}</small
        >
      </div>
    </div>
    <div class="message-container">
      <div id="message" />
      <button type="submit" class="btn btn-amsom-green" :disabled="isSending">
        <font-awesome-icon v-if="!isSending" icon="paper-plane" />
        <div v-else class="spinner-border spinner-border-sm" role="status">
          <span class="visually-hidden">Envois en cours...</span>
        </div>
      </button>
    </div>
  </form>
</template>

解决方案

1. 修正清空范围 + 延迟执行

Quill编辑器默认会保留一个换行符(长度为1),如果删除范围包含这个默认换行符,会导致内部状态异常。同时,$emit后父组件可能触发DOM更新,用$nextTick延迟清空操作:

handleSubmission() {
  const message = this.quill.getContents()
  this.$emit('new-message', message)
  this.$nextTick(() => {
    // 只删除内容部分,保留默认换行符
    this.quill.deleteText(0, this.quill.getLength() - 1)
  })
}

2. 改用Ref获取DOM元素初始化Quill(推荐)

直接使用ID选择器初始化Quill存在全局冲突风险,改用Vue的ref绑定DOM元素更可靠:

  • 模板中修改编辑器容器:
<div ref="messageEditor" />
  • 初始化Quill时使用ref获取元素:
mounted() {
  this.quill = new Quill(this.$refs.messageEditor, {
    theme: 'bubble',
    modules: {
      toolbar: [
        ['bold', 'italic', { color: [] }],
        [{ list: 'ordered' }, { list: 'bullet' }]
      ]
    }
  })
}

3. 重置为默认空状态

如果上述方法无效,可直接将编辑器内容重置为Quill默认的空状态(仅保留一个换行符):

handleSubmission() {
  if (!this.quill || !this.quill.root) return
  const message = this.quill.getContents()
  this.$emit('new-message', message)
  this.quill.setContents([{ insert: '\n' }])
}

内容的提问来源于stack exchange,提问作者LuckyFox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 13:45:55