如何在聊天中点击链接

时间:2018-01-28 06:16:40

标签: html json vue.js

我在我的网站上聊天,从JSON文件中读取并抓取每条消息,然后使用 Vue.js 显示它。但是,我的问题是,当用户发布链接时,它不包含在锚标记<a href=""/>中。因此无法点击。

我看到了这个post,我认为这样的东西会起作用,但是,我不允许向网站添加任何更多依赖项。我是否有办法在不添加更多依赖项的情况下做类似的事情?

显示信息的代码。

<p v-for="msg in messages">
    <em class="plebe">
        <b>&nbsp;[ {{msg.platform.toUpperCase()}} ]&nbsp;
            <span style="color: red" v-if="msg.isadmin">{{msg.user.toUpperCase()}}</span>
            <span style="color: #afd6f8" v-else="">{{msg.user.toUpperCase()}}</span>
        </b>
    </em>:&nbsp;
    {{msg.message}}
</p>

2 个答案:

答案 0 :(得分:1)

在这种情况下,它首选编写自定义功能组件。

原因是我们需要发出一个复杂的html结构,但我们必须确保正确防范xss攻击(所以v-html + http regex不在图片中)

我们也将使用渲染函数,因为渲染函数的优点是允许生成html的javascript具有更大的自由度。

<!-- chatLine.vue -->
<script>
    export default {
        functional: true,
        render: function (createElement, context) {
            // ...
        },
        props: {
            line: {
                type: String,
                required: true,
            },
        },
    };
</script>
<style>
</style>

我们现在需要考虑如何解析实际的聊天消息,为此,我将使用一个正则表达式,分割任何长度的空格(要求我们的聊天网址被空格包围,或者他们是在行的开头或结尾。)

我现在要按以下方式编写代码:

  1. 列出子组件列表
  2. 使用正则表达式在目标字符串
  3. 中查找网址
  4. 对于找到的每个网址,请执行以下操作:
    1. 如果匹配不在开头,则将上一个匹配/开头的文本放在子项内
    2. 将网址列在子项列表中作为<a>标记,并使用正确的href属性
  5. 最后,如果我们仍然留下了字符,那么他们也会留下孩子名单
  6. 返回包含在P元素中的列表
  7. Vue.component('chat-line', {
      functional: true,
      // To compensate for the lack of an instance,
      // we are now provided a 2nd context argument.
      // https://vuejs.org/v2/guide/render-function.html#createElement-Arguments
      render: function (createElement, context) {
        const children = [];
        let lastMatchEnd = 0;
        // Todo, maybe use a better url regex, this one is made up from my head
        const urlRegex = /https?:\/\/([a-zA-Z0-9.-]+(?:\/[a-zA-Z0-9.%:_()+=-]*)*(?:\?[a-zA-Z0-9.%:_+&/()=-]*)?(?:#[a-zA-Z0-9.%:()_+=-]*)?)/g;
        const line = context.props.line;
        let match;
        while(match = urlRegex.exec(line)) {
          if(match.index - lastMatchEnd > 0) {
            children.push(line.substring(lastMatchEnd, match.index));
          }
          children.push(createElement('a', {
            attrs:{
              href: match[0],
            }
          }, match[1])); // Using capture group 1 instead of 0 to demonstrate that we can alter the text
          lastMatchEnd = urlRegex.lastIndex;
        }
        if(lastMatchEnd < line.length) {
          // line.length - lastMatchEnd
          children.push(line.substring(lastMatchEnd, line.length));
        }
        return createElement('p', {class: 'chat-line'}, children)
      },
      // Props are optional
      props: {
        line: {
          required: true,
          type: String,
        },
      },
    });
    
    var app = new Vue({
      el: '#app',
      data: {
        message: 'Hello <script>, visit me at http://stackoverflow.com! Also see http://example.com/?celebrate=true'
      },
    });
    .chat-line {
      /* Support enters in our demo, propably not needed in production */
      white-space: pre;
    }
    <script src="https://unpkg.com/vue@2.0.1/dist/vue.js"></script>
    <div id="app">
      <p>Message:</p>
      <textarea v-model="message" style="display: block; min-width: 100%;"></textarea>
      
      <p>Output:</p>
      <chat-line :line="message"></chat-line>
    </div>

答案 1 :(得分:0)

您可以watch or write computed method获取包含网址的变量并将其更改为html内容,然后使用v-html在网页上显示html内容

v-html