首页 > 解决方案 > 替换标签动态返回对象而不是内容

问题描述

我正在构建一个聊天客户端,我想扫描特定标签的消息,在这种情况下[item:42]

我将消息一一传递给以下组件:

<script>
import ChatItem from './ChatItem'

export default {
    props :[
        'chat'
    ],

    name: 'chat-parser',

    data() {
        return {
            testData: []
        }
    },

    methods : {
        parseMessage(msg, createElement){
            const regex = /(?:\[\[item:([0-9]+)\]\])+/gm;
            let m;

            while ((m = regex.exec(msg)) !== null) {
                msg = msg.replace(m[0],
                    createElement(ChatItem, {
                        props : {
                            "id" : m[1],
                        },
                    }))


                if (m.index === regex.lastIndex) {
                    regex.lastIndex++;
                }
            }


            return msg
        },

    },

    render(createElement) {
        let user = "";
        let msg  = this.parseMessage(this.$props.chat.Message, createElement)

        return createElement(
            'div',
            {

            },
            [
                 // "hello",// createElement("render function")
                createElement('span', '['+ this.$props.chat.Time+'] '),
                user,
                msg,
            ]
        )

    }
};

</script>

我认为传递createElement给该parseMessage方法是一个好主意,但它无法正常工作,因为它将标签替换为[object object]

chatItem 看起来像这样:

<template>
    <div>
        <span v-model="item">chatITem : {{ id }}</span>
    </div>
</template>

<script>
    export default {
        data: function () {
            return {
                item : [],
            }
        },

        props :['id'],

        created() {
            // this.getItem()
        },

        methods: {
             getItem: function(){
               obj.item = ["id" : "42", "name": "some name"]
             },

        },
    }
</script>

例子 :

如果消息看起来像这样:what about [item:42] OR [item:24]两者都需要替换为 chatItem 组件

标签: vue.jsvue-component

解决方案


render如果您只是将文本解析为模板可以使用的格式,则可以使用并非真正需要的函数来完成此操作。

在这种情况下,我保持解析器非常原始。它产生一个值数组。如果一个值是一个字符串,那么模板只是将它转储出去。如果该值是一个数字,则假定它是从中提取[item:24]并传递给 a 的数字<chat-item>。我使用了一个虚拟版本<chat-item>,它只输出<strong>标签中的数字。

new Vue({
  el: '#app',
 
  components: {
    ChatItem: {
      props: ['id'],
      template: '<strong>{{ id }}</strong>'
    }
  },

  data () {
    return {
      text: 'Some text with [item:24] and [item:42]'
    }
  },
  
  computed: {
    richText () {
      const text = this.text

      // The parentheses ensure that split doesn't throw anything away
      const re = /(\[item:\d+\])/g

      // The filter gets rid of any empty strings
      const parts = text.split(re).filter(item => item)
      
      return parts.map(part => {
        if (part.match(re)) {
          // This just converts '[item:24]' to the number 24
          return +part.slice(6, -1)
        }
        
        return part
      })
    }
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
  <template v-for="part in richText">
    <chat-item v-if="typeof part === 'number'" :id="part"></chat-item>
    <template v-else>{{ part }}</template>
  </template>
</div>

如果我打算用一个render函数来做,我会以几乎相同的方式来做,只是用一个render函数替换模板。

如果文本解析要求稍微复杂一点,那么我不会只返回字符串和数字。相反,我会使用对象来描述每个部分。但核心思想保持不变。


推荐阅读