如何将HTML模板作为道具传递给Vue组件

Ehs*_*Ali 5 html javascript vue.js

我有一个textarea包含的组件,html tag我想html在此组件中进入编辑模式。我Laravel用来生成HTML。

<template>
    <div>
        <textarea
                  :value="content"
                  :name="name"
                  :id="id">
              <slot></slot>
        </textarea>
    </div>
</template>
Run Code Online (Sandbox Code Playgroud)

在刀片页面中,我习惯了此组件:

<my-component>
   <p class="textbox">hello world</p>
</my-component>
Run Code Online (Sandbox Code Playgroud)

当我将此组件放在页面中时,<slot></slot>在textarea中显示标签。我该怎么办?您有我需要的解决方案吗?

谢谢

acd*_*ior 9

<textarea>Vue渲染器将组件视为静态组件,因此在将它们放入DOM后,它们根本不会发生变化(因此,如果您检查DOM,就会<slot></slot>在自己的内部看到<textarea>)。

但是即使他们做了改变,也无济于事。仅仅因为<textarea>s中的HTML元素没有成为它们的价值。您必须设置TextArea元素value属性以使其起作用。

无论如何,不​​要绝望。这是可行的,克服上述问题所需要做的就是发挥一个小的辅助组件的作用。

有多种方法可以实现此目的,下面显示了两种。它们在根本上的不同之处在于您希望原始组件模板的样式。

解决方案:更改<textarea><textarea-slot>组件

您组件的模板现在将变为:

<template>
    <div>
      <textarea-slot
                v-model="myContent"
                :name="name"
                :id="id">
            <slot></slot>
      </textarea-slot>
    </div>
</template>
Run Code Online (Sandbox Code Playgroud)

如您所见,只不过被替换<textarea>了而已<textarea-slot>。这足以克服Vue给予的静态处理<textarea>。的完整实现<textarea-slot>在下面的演示中。

替代解决方案:保留<textarea><slot>通过<vnode-to-html>组件获取HTML

解决方案是创建一个帮助器组件(命名vnode-to-html如下),该组件会将插槽的VNode转换为HTML字符串。然后,您可以设定HTML字符串作为value你的<textarea>。您组件的模板现在将变为:

<template>
    <div>
        <vnode-to-html :vnode="$slots.default" @html="valForMyTextArea = $event" />
        <textarea
                  :value="valForMyTextArea"
                  :name="name"
                  :id="id">
        </textarea>
    </div>
</template>
Run Code Online (Sandbox Code Playgroud)

在这两种选择中...

my-component保持不变的用法:

<my-component>
   <p class="textbox">hello world</p>
</my-component>
Run Code Online (Sandbox Code Playgroud)


完整的工作演示:

<template>
    <div>
      <textarea-slot
                v-model="myContent"
                :name="name"
                :id="id">
            <slot></slot>
      </textarea-slot>
    </div>
</template>
Run Code Online (Sandbox Code Playgroud)
<template>
    <div>
        <vnode-to-html :vnode="$slots.default" @html="valForMyTextArea = $event" />
        <textarea
                  :value="valForMyTextArea"
                  :name="name"
                  :id="id">
        </textarea>
    </div>
</template>
Run Code Online (Sandbox Code Playgroud)

分解:

  • Vue将<slot>s 解析为VNodes,并使它们在this.$slots.SLOTNAME属性中可用。自然,默认插槽进入this.$slots.default
  • 因此,在运行时中,您可以使用已通过的内容<slot>(如中的VNodes this.$slots.default)。现在的挑战变成了如何将这些VNode转换为HTML String?这是一个复杂但仍未解决的问题,将来可能会获得不同的解决方案,但是即使这样做,也很可能需要一段时间
  • 上面(template-slotvnode-to-html)的两个解决方案都使用Vue的render函数将VNode渲染到DOM,然后拾取渲染的HTML。
  • 由于提供的插槽可以具有任意HTML,因此我们将VNode渲染为HTML模板元素,该元素不会执行任何<script>标签。
  • 两种解决方案之间的区别在于,它们如何“处理”从渲染函数生成的HTML。
    • vnode-to-html返回作为应该由父(被拾起的事件my-component),其使用所传递的值来设置data将被设置为属性:valuetextarea
    • textarea-slot声明本身<textarea>,父不就得了。这是一种更干净的解决方案,但需要多加注意,因为您必须指定要将哪些属性传递给<textarea>created内部textarea-slot


包装和现成的替代品

无论可能如何,重要的是要知道Vue在将声明的内容解析<template><slot>s时,会剥离一些格式信息,例如顶级组件之间的空格。同样,它会剥离<script>标签(因为它们不安全)。这些是使用<slot>s(在此显示或不显示)的任何解决方案固有的警告。所以要注意。

Vue的典型RTF编辑器通过使用v-model(或value)属性将代码传递到组件中来完全解决此问题。

众所周知的例子包括:

他们在他们的网站上都有非常好的文档(上面有链接),所以在这里重复它们对我没有多大用处,但仅作为示例,请看codemirror如何使用valueprop传递代码:

<codemirror ref="myCm"
            :value="code" 
            :options="cmOptions"
            @ready="onCmReady"
            @focus="onCmFocus"
            @input="onCmCodeChange">
</codemirror>
Run Code Online (Sandbox Code Playgroud)

这就是他们的做法。当然,如果<slot>s(带有警告)适合您的用例,则也可以使用它们。


Vo *_*yen 5

简短的答案是不可能的

您的广告位将放在textarea标签内。Textare标签只能在其框上显示文本内容。

因此,如果您需要一种“ HTML编辑模式”,则可能需要使用WYSIWYG编辑器,我建议您可以将CKEditor用于VueJS,该编辑器甚至可以直接编辑HTML代码

https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/frameworks/vuejs.html

您的HTML

<div id="app">
    <ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
</div>
Run Code Online (Sandbox Code Playgroud)

您的组件

const app = new Vue( {
    el: '#app',
    data: {
        editor: ClassicEditor,
        editorData: '<p>Editable Content HTML</p>',
        editorConfig: {
            // The configuration of the editor.
        }
    }
} );
Run Code Online (Sandbox Code Playgroud)