最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Vue js render text with html content - Stack Overflow

programmeradmin0浏览0评论

What i'm trying to do is have a root element with a prop that holds inner html like: hello<b>hey</b> but i can't use v-html because this element also has children for example:

<template>
  <ponent :is="element.tag" contenteditable="true">
    <div contenteditable="false">
      <span class="delete-obj" :id="'delete'+element.id" >delete</span>
    </div>
    <RenderString :string="element.content" />
  </ponent>
</template>
<script>
    import Vue from "vue";
  
    Vueponent("RenderString", {
        props: {
            string: {
                required: true,
                type: String
            }
        },
        render(h) {
            const render = {
                template:  this.string ,
                methods: {
                    markComplete() {
                        console.log('the method called')
                    }
                }
            }
            return h(render)
        }
    })
    export default {
        name: "VElement",
        props: {
            element: {
                required: false,
                default: null
            },
        },
    }
 </script>

I have tried the above and I have tried using slots. I can solve it with vanilla JavaScript like element.innerText, but I don't want to. The main goal is that the element is editable when they type they are editing element.content that will be rendered and the div that's inside it is normal HTML that I also need. The main problem is that the inner HTML that I want doesn't have a root element. The element is something like:

{id:1,tag:"div",content:"hello<b>hey</b>"}

I want the final result to be:

<div contenteditable="true">
    <div contenteditable="false">
        <span class="delete-obj" :id="'delete'+element.id" >delete</span>
    </div>
    hello<b>hey</b>
<div>

And I want to edit hello<b>hey</b> when I click inside I don't want it wrapped in anything else and if I put v-html on the outer div the inner div is gone.

What i'm trying to do is have a root element with a prop that holds inner html like: hello<b>hey</b> but i can't use v-html because this element also has children for example:

<template>
  <ponent :is="element.tag" contenteditable="true">
    <div contenteditable="false">
      <span class="delete-obj" :id="'delete'+element.id" >delete</span>
    </div>
    <RenderString :string="element.content" />
  </ponent>
</template>
<script>
    import Vue from "vue";
  
    Vue.ponent("RenderString", {
        props: {
            string: {
                required: true,
                type: String
            }
        },
        render(h) {
            const render = {
                template:  this.string ,
                methods: {
                    markComplete() {
                        console.log('the method called')
                    }
                }
            }
            return h(render)
        }
    })
    export default {
        name: "VElement",
        props: {
            element: {
                required: false,
                default: null
            },
        },
    }
 </script>

I have tried the above and I have tried using slots. I can solve it with vanilla JavaScript like element.innerText, but I don't want to. The main goal is that the element is editable when they type they are editing element.content that will be rendered and the div that's inside it is normal HTML that I also need. The main problem is that the inner HTML that I want doesn't have a root element. The element is something like:

{id:1,tag:"div",content:"hello<b>hey</b>"}

I want the final result to be:

<div contenteditable="true">
    <div contenteditable="false">
        <span class="delete-obj" :id="'delete'+element.id" >delete</span>
    </div>
    hello<b>hey</b>
<div>

And I want to edit hello<b>hey</b> when I click inside I don't want it wrapped in anything else and if I put v-html on the outer div the inner div is gone.

Share Improve this question edited May 8, 2021 at 15:37 karel 5,89560 gold badges57 silver badges59 bronze badges asked Apr 29, 2021 at 21:52 Girl CodesGirl Codes 3784 silver badges18 bronze badges 5
  • Where is your script block? You're using element but you're not showing where it was defined – Jonathan Commented Apr 29, 2021 at 21:58
  • @Jonathan the script got nothing important but i edited to show you and the element is as simple as that – Girl Codes Commented Apr 29, 2021 at 22:04
  • The v-html directive should work with a string like "hello<b>hey</b>" – Seblor Commented May 1, 2021 at 23:30
  • Is your problem content of <div contenteditable="false"> being edited by user? – T J Commented May 2, 2021 at 7:29
  • @Seblor yes i know that works but putting it on the outer div the <div contenteditable="false"> is gone and replaced with the string – Girl Codes Commented May 2, 2021 at 9:56
Add a ment  | 

2 Answers 2

Reset to default 2

Like Seblor said, v-html will work with nested html strings.

Simply replacing the RenderString ponent with a <div v-html="element.content"/> should get you what you want.

Tested with the given example of hello<b>hey</b>:

Vue.ponent('VElement', {
  name: "VElement",
  props: {
    element: {
      required: false,
      default: null
    },
  },
  template: '\
    <ponent :is="element.tag" contenteditable="true">\
      <div contenteditable="false">\
        <span class="delete-obj" :id="\'delete\'+element.id">delete</span>\
      </div>\
      <div v-html="element.content"/>\
    </ponent>'
})

new Vue({
  el: '#app'
})
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <v-element :element="{id:1, tag:'div', content:'hello<b>hey</b>'}" />
</div>

If you really aren't able to wrap the content in a parent element, maybe a good approach is to write a VUE directive that render the text.

JS FIDDLE FULL DEMO

//DIRECTIVE
Vue.directive('string', {
    inserted(el, bind) {
        /** 
        * Here you can manipulate the element as you need.
        */

        el.insertAdjacentText('beforeend', bind.value); 
    }
});

//TEMPLATE
<template>
  <ponent :is="element.tag" contenteditable="true" v-string="element.content">
    <div contenteditable="false">
      <span>delete</span>
    </div>
  </ponent>
</template>
发布评论

评论列表(0)

  1. 暂无评论