如何使链接在聊天中可点击 [英] How to make links clickable in a chat

查看:152
本文介绍了如何使链接在聊天中可点击的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我看到这个 post ,我认为类似这样的工作,但是,我不允许添加任何更多的依赖关系的网站。有没有办法让我在不增加更多依赖的情况下做类似的事情?



显示消息的代码。

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


解决方案

在这样的情况下,自定义功能组件。



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



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

 <! -  chatLine.vue  - > 
< script>
导出默认值{
功能:true,
render:function(createElement,context){
// ...
},
道具:{
line:{
type:String,
required:true,
},
},
};
< / script>
< style>
< / style>

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



我现在要按照以下方式创建代码:


  1. 为子组件列出一个列表

  2. 使用正则表达式在目标字符串中查找url
  3. 对于找到的每个url,执行:


    1. 如果比赛没有开始,请将从前一场比赛开始的文字放入孩子里

    2. 将网址放在孩子列表中,作为


    3. 最后,如果我们仍然有字符留在他们的孩子列表

    4. 返回我们的列表包装在P元素里

      Vue.component('chat-line',{functional:true,//为了补偿缺少实例,//我们现在提供了第二个上下文参数。 // https://vuejs.org/v2/guide/render-function.html#createElement-Arguments render:function(createElement,context){const children = [];让lastMatchEnd = 0; // Todo,也许使用更好的url正则表达式,这个由我的头构成const urlRegex = /https?:\/\/([a-zA-Z0-9.--]+(?:\ /[a-zA-Z0-9.%:_()+=-]*)*(?:\?[a-zA-Z0-9.%:_+&/()=-]* )?(:#?[A-ZA-Z0-9%:()_ + =  - ] *))/克; const line = context.props.line;比赛; 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])); //使用捕获组1而不是0来证明我们可以改变文本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是可选的道具:{line:{required:true,type:String,},},}); var app = new Vue({el:'#app',data:{message:'Hello< script>,请访问我http://stackoverflow.com!另请参阅http://example.com/?celebrate=true' },});  

    .chat-line {/ *支持进入我们的演示,在生产中不需要支持* / white-space:pre;}

     < script src =https://unpkg.com/vue@2.0.1/dist/vue.js>< / script>< div id =app> ; < P>消息:其中/ p为H. < textarea v-model =messagestyle =display:block; min-width:100%;>< / textarea> < p为H.;输出:其中/ p为H. < chat-line:line =message>< / chat-line>< / div>  


    I have a chat on my website that reads from a JSON file and grabs each message and then displays it using Vue.js. However, my problem is that when a user posts a link, it is not contained in an anchor tag <a href=""/>. Therefore it is not clickable.

    I saw this post, and I think something like this would work, however, I am not allowed to add any more dependencies to the site. Would there be a way for me to do something similar to this without adding more dependencies?

    Code for displaying the message.

    <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>
    

    解决方案

    In a situation like this, its preferred to write a custom functional component.

    The reason for this is the fact that we are required to emit a complex html structure, but we have to make sure to properly protect against xss attacks (so v-html + http regex is out of the picture)

    We are also going to use render functions, because render functions have the advantage to allow for javascript that generates the html, having more freedom.

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

    We now need to think about how to parse the actual chat message, for this purpose, I'm going to use a regex that splits on any length of whitespace (requiring our chat urls to be surrounded with spaces, or that they are at the start or end of line).

    I'm now going to make the code in the following way:

    1. Make a list for child componenets
    2. Use a regex to find url's inside the target string
    3. For every url found, do:

      1. If the match isn't at the start, place the text leading from the previous match/start inside the children
      2. place the url inside the list of children as an <a> tag, with the proper href attribute

    4. At the end, if we still have characters left, at them to the list of children too
    5. return our list wrapped inside a P element

    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>

    这篇关于如何使链接在聊天中可点击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆