Replace标签动态返回对象而不是内容

时间:2019-07-05 14:32:25

标签: vue.js vue-component

我正在构建一个聊天客户端,我想扫描消息中的特定标签,在这种情况下为[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组件替换

1 个答案:

答案 0 :(得分:1)

虽然您可以使用render函数来做到这一点,但是如果您只是将文本解析为模板可以使用的格式,则并不需要。

在这种情况下,我保持解析器非常原始。它产生一个值数组。如果值是字符串,则模板会将其转储出去。如果该值为数字,则假定为从[item:24]中提取并传递给<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函数。

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