How to replace a string with a component (vue)

2019-07-29 04:08发布

I have strings that contains ### and I am replacing with array values. Now I want to use them with a component, I created the component and it works but I don't know how to use it in the strings. I don't want to wrap them manually because I don't know how the strings will be, it can have several ###. If it has 2 ###, options will have 2 subArrays.

What is the better way to do it?

Code: https://jsfiddle.net/tsobh4nu/

Vue.component('opt', {
  template: `<label>
                <span class="bold" v-for="(str,idx) in options">
                     {{str + " / "}}
                </span>
             </label>`,
  props:{options: Array}
})

new Vue({
  el: '#app',
  data: {
    str: "I have ### and you have a ###.",
      options: [
        ['AAA', 'BBB', 'CCC'],
        ['XXX', 'YYY', 'ZZZ']
      ]
  },
  computed:{
  	replacedStr(){
    	let newStr = this.str;
      this.options.forEach(option=>{
      	newStr = newStr.replace('###',this.concatenateOptions(option));
      })
      return newStr;
    }
  },
  methods: {
    concatenateOptions(strArr) {
      let separator = "";
      let strOptions = "";
      strArr.forEach(word => {
        strOptions += separator  + word;
        separator = " / ";
      });
      return strOptions;
    }
  }
})
.bold {
  font-weight: bold
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
  <p>I want something like this, but using components: </p>
  {{replacedStr}}
  <br>
  <hr>
  My Components:<br>
  <opt :options="options[0]"></opt>
  <br>
  <opt :options="options[1]"></opt>
</div>

Many thanks.

2条回答
做个烂人
2楼-- · 2019-07-29 04:31

This is more general, but I hope it will help someone. Add a dynamic component in your template: <component v-bind:is="processedHtml"></component>.

Then add a computed method:

computed: {
    processedHtml () {
        let html = this.html.replace('[Placeholder]', '<my-component></my-component>');
        return {
            template: '<div>' + html + '</div>'
        }
     }
}

Where <my-component> is your custom component and the this.html is your HTML content that contains the placeholder [Placeholder].

It is important to return an element that has one root node. That's why the return is wrapped with <div>.

Read more advanced tutorial about this issue here in my blog. For example, to pass props to <my-component>

查看更多
一纸荒年 Trace。
3楼-- · 2019-07-29 04:42

You need to move up the food chain ! You're going to lengths to bypass the goodness of vue. Your data.string is a template, and your ### is a not very meaningful placeholder, and then you have to do the work yourself.

Can't you use Vue's templating system? And your concatenateOptions method can be replaced with Array.join().

查看更多
登录 后发表回答