请问vue3使用innerhtml,照片渲染不出来,该怎么处理?

image.png
image.png
如图,使用innerhtml渲染用户发送出的内容,但是头像无法渲染出来,请问该如何处理?
js代码如下

send(){
      let text = document.querySelector('#send-text').value;
      if(!text){
        alert('请输入内容');
        return ;
      }
      let item = document.createElement('div');
      item.className = 'item item-right';
      item.style='';
      item.innerHTML = `
                        <div class="right-message"
                        style="background-color: #fefeff;
                                color: #555;
                                float: right;
                                word-wrap: break-word !important;
                                padding: 8px 10px;
                                border-radius: 8px 2px 8px 8px;
                                margin-right: 8px;
                                max-width: 220px;
                                font-size: 15px;
                                line-height: normal;">
                            <span>${text}</span>
                        </div>
                        <div class="avatar">
                           <img src="@/assets/user.png" alt="user-icon"
                                style="width: 42px;
                                        height: 42px;
                                        border-radius: 50px;
                                        border: 1.8px solid #cdcdcd;"/>
                        </div>


                        `;

      document.querySelector('.talk-box').appendChild(item);
      document.querySelector('#send-text').value = '';
      document.querySelector('#send-text').focus();
      //滚动条置底
      let height = document.querySelector('.talk-box').scrollHeight;
      document.querySelector(".talk-box").scrollTop = height;
      console.log("发送出去")
      // answer(text)
    },

html如下:

<div id="chat-block" style="display: block">
        <div class="chat-container">
          <div class="chat-header">
            <div class="doctor-name">{{doctorList.name}}</div>
            <div class="icon-shrink">
              <img src="@/assets/shrink.png" alt="shrink-icon" class="shrink" @click="closeTalk()"/>
            </div>
          </div>


          <div class="content">
            <div class="talk-box">
              <div class="item item-left">
                <div class="avatar">
                  <img src="@/assets/doctor.png" alt="docter-icon"/>
                </div>
                <div class="left-message">
                  <span>您好,请详细描述您的问题,我会尽快回复。</span>
                </div>
              </div>

              <div class="item item-right">

              </div>


            </div>

          </div>

          <div class="input-area">

            <textarea type="text" id="send-text" placeholder="请输入您的问题"></textarea>
            <div class="send-block">
              <img src="@/assets/send_message.png" alt="icon-send" class="send-button" @click="send()"/>

            </div>
          </div>
        </div>
      </div>

请赐教,不胜感激。

阅读 6.5k
4 个回答

使用动态组件,代替innerHTML。
或者使用可用的图片路径,相对路径,或者绝对路径

都用 Vue 了,为啥还要 innerHTML?这种写法就是错误的。

至于头像渲染不出来,多半是因为你代码里的 @/assets/。使用 Vue 的时候,<template> 会编译成模版函数,然后通过 webpack 处理依赖关系,然后执行,所以路径里可以有 @ 别名。你手动插入的话,就得自己处理这些问题。

建议尽早改成组件,适应 Vue 开发。

你使用 vue 开发,应该遵循数据(js)驱动视图(html)的原则,非极端情况下应避免直接操作 html

在你的用例中,你可以在 data 里定义一个会话列表,在模版里根据这个列表用 v-for 进行会话记录渲染,在有新的会话时,往该列表 push 一个会话,通过响应式数据模版会根据新添加的会话渲染。

下面是一个简单代码示例,你理解里面的内容后自己做调整即可(都是手打的可能有拼错):

<template>
  <ul class="message-list">
    <li v-for="(msg, index) in messageList" :key="index" class="message">
      <!-- 这 li 里是你的 innerHTML 的代码 -->
      <div
        class="right-message"
        style="
          background-color: #fefeff;
          color: #555;
          float: right;
          word-wrap: break-word !important;
          padding: 8px 10px;
          border-radius: 8px 2px 8px 8px;
          margin-right: 8px;
          max-width: 220px;
          font-size: 15px;
          line-height: normal;
        "
      >
        <span>{{ msg.text }}</span>
      </div>
      <div class="avatar">
        <img
          src="@/assets/user.png"
          alt="user-icon"
          style="
            width: 42px;
            height: 42px;
            border-radius: 50px;
            border: 1.8px solid #cdcdcd;
          "
        />
      </div>
    </li>
  </ul>

  <!-- 输入框,其他的 html 省略 -->
  <div class="input-area">
    <!-- 获取输入框里的值,应使用 v-model 或者使用 ref 获取元素再获取值 -->
    <!-- 而不应该用 document.querySelector 等方式,下例用 ref 的形式 -->
    <textarea ref="textarea" type="text" id="send-text" placeholder="请输入您的问题"></textarea>
    <div class="send-block">
      <img
        src="@/assets/send_message.png"
        alt="icon-send"
        class="send-button"
        @click="send()"
      />
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 储存会话数据
      messageList: [
        // { text: '聊天记录' }
      ]
    }
  },
  methods: {
    send() {
      const textarea = this.$refs.textarea
      const sendText = textarea?.value

      if(!text){
        alert('请输入内容')
        return
      }

      this.messageList.push({ text: sendText })
      textarea.value = ''
      textarea.focus()

      // 滚动条置底等操作也应该用 ref 的方式获取到 html 元素进行操作,此处省略
    }
  }
}
</script>

由于图片路径中的 @/assets/send_message.png 导致的,走HTML模板,webpack不会解析转换路径,可以用

const imgUrl = require('@/assets/send_message.png') 

先用变量接收,在拼接到img的src

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题