简体   繁体   English

如何在聊天中使链接可点击

[英]How to make links clickable in a chat

I have a chat on my website that reads from a JSON file and grabs each message and then displays it using Vue.js .我在我的网站上有一个聊天,它从 JSON 文件中读取并抓取每条消息,然后使用Vue.js显示它。 However, my problem is that when a user posts a link, it is not contained in an anchor tag <a href=""/> .但是,我的问题是,当用户发布链接时,它不包含在锚标记<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)原因是我们需要发出复杂的 html 结构,但我们必须确保适当地防止 xss 攻击(因此 v-html + http 正则表达式不在图片中)

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.我们还将使用渲染函数,因为渲染函数的优点是允许 javascript 生成 html,具有更大的自由度。

<!-- 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).我们现在需要考虑如何解析实际的聊天消息,为此,我将使用一个在任意长度的空格上拆分的正则表达式(要求我们的聊天 url 用空格包围,或者它们位于行的开始或结束)。

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使用正则表达式在目标字符串中查找 url
  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将 url 作为<a>标记放在子列表中,并带有适当的 href 属性
  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返回包装在 P 元素中的列表

 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>

You can watch or write computed method for the variable having url and manupulate it to html content and then use v-html to show html content on the page您可以watch or write computed method并将其处理为 html 内容,然后使用v-html在页面上显示 html 内容

v-html v-html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM