【问题标题】:How to convert a mention tag text to a <router-link> ? (VUEJS)如何将提及标签文本转换为 <router-link> ? (VUEJS)
【发布时间】:2020-11-13 06:51:08
【问题描述】:

我在 data 中有一个 body 属性

data(){
 return{
  body:'Hello im @username1 and @username2'
 }
}

我想将每个@user 转换为下面的代码,用户可以在其中单击该链接以转到该 url 路径。

<router-link :to="`/${username1}`">@{{username1}}</router-link>

我尝试了什么

<span v-html='bodyReplaced'>
  computed: {
    bodyReplaced(){
      return this.body.replace(
        /@\w+/g, 
        (user) => '<router-link :to="`/${username1}`">@{{username1}}</router-link>'
      )
    }
  }

代码做了什么:

  1. 将字符串转换为dom中的router-link而不是视图中
  2. 我不知道如何在匹配后替换 @,所以我可以在 to="`/${username1} 中使用它

【问题讨论】:

  • 假设您可以用 router-link 组件替换提到的用户,但是这将不起作用,因为无法解析组件(路由器链接)
  • 不要试图弄乱字符串。在模板中编写函数,使用纯字符串或路由器链接呈现实际组件列表。
  • 我明白了,这怎么行?有什么例子吗? @Bergi

标签: javascript vue.js vuejs2 vue-component vue-router


【解决方案1】:

创建一个名为 mention 的组件并将用户名作为 prop 传递,我使用了与 @Bergi 相同的方法,或者您可以替换一个计算属性,在其中将提及 uder 替换为可以解析的 a 元素不像路由器链接:

Vue.component('mention', {
  template: `<router-link :to="'/'+user">@{{user}}</router-link>`,
  props: ['user']
})
const Foo = {
  template: '<div>im foo</div>'
}
const Bar = {
  template: '<div>im bar</div>'
}
const routes = [{
    path: '/foo',
    component: Foo
  },
  {
    path: '/bar',
    component: Bar
  }
]

const router = new VueRouter({
  routes, // short for `routes: routes`,

})

// 4. Create and mount the root instance.
// Make sure to inject the router with the router option to make the
// whole app router-aware.
const app = new Vue({
  router,
  data() {
    return {
      body: 'Hello im @foo and @bar'
    }
  },

  computed: {
    tokens() {
      return this.body.split(' ');
    },
    bodyReplaced() {
      return this.body.split(' ').map(w => {
        return w.startsWith('@') ? `<a href="#/${w.slice(1)}">${w}</a>` : w;
      }).join(' ')
    }
  }
}).$mount('#app')
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app">
  <div>********The first solution********</div>

  <template v-for="token in tokens">
    
     <mention v-if="token.startsWith('@')" :user="token.slice(1)"></mention>
     <template v-else>&nbsp;{{token}}&nbsp;</template>
  </template>
  <div>********The second solution********</div>
  <span v-html='bodyReplaced'></span>
  <router-view></router-view>
</div>

【讨论】:

  • 好的,让我试试,然后回复你,你这是唯一的方法吗?我认为这个动作太冗长了,或者你认为没问题?
  • 请检查第二个解决方案,我认为它接近您的方法
  • 我想要第二种解决方案,这必须像您的第二种方法一样简单,这里的问题是,它的 aa 标签,是否可以使用 router-link 进行第二种方法?
  • 正如官方docs 中提到的:请注意,您不能使用 v-html 来编写模板部分,因为 Vue 不是基于字符串的模板引擎。相反,组件被首选作为 UI 重用和组合的基本单元,因此路由器链接是 vue 组件而不是 html 元素,它不会被解析,它将显示为原始 html
  • 当然,而且很简单,只需在 a 标签中添加一个类就可以了,感谢您的支持。我认为使用标签而不是路由器链接没有性能问题,他们会做同样的事情
【解决方案2】:

我认为您正在寻找类似的东西

<template v-for="part of body.split(/(@\w+)/g)">
  <router-link v-if="part[0] == '@'" :to="`/${part.slice(1)}`">{{part}}</router-link>
  <template v-else>{{part}}</template>
</template>

new Vue({
  el: 'main',
  data: {
    body:'Hello im @username1 and @username2'
  },
  router: new VueRouter({
    routes: []
  }),
})
<main>
  <template v-for="part of body.split(/(@\w+)/g)">
    <router-link v-if="part[0] == '@'" :to="`/${part.slice(1)}`">{{part}}</router-link>
    <template v-else>{{part}}</template>
  </template>
</main>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

【讨论】:

  • 嗨,我正在使用你的代码,我得到了这个控制台错误属性或方法“部分”未在实例上定义,但在渲染期间引用@Bergi
  • 应该是v-for
  • @AlexHunter 就像 NickG 说的,我把 v-for 拼错为 for。添加了完整的示例。
  • 我也看到了,使用 v-for,但是使用 v-for 现在得到这个错误迭代中的自定义元素需要'v-bind:key'指令@Bergi
  • @AlexHunter 这是一个实际错误还是只是一个 linter 投诉?上面的 sn-p 有效。我想key 对于这么短的列表来说并不是必需的。如果你真的想要,you can use the index as a key
猜你喜欢
  • 2018-04-26
  • 2018-12-05
  • 1970-01-01
  • 2023-04-04
  • 2018-03-17
  • 1970-01-01
  • 2020-02-22
  • 1970-01-01
  • 2018-01-20
相关资源
最近更新 更多