Vue mixin渲染HTML并附加到$ref



我想使用一个mixin来找到一个引用的Node,然后在它上面附加一些使用Vue渲染的HTML,这样我就可以将数据传递给它。

const Tutorial = guide => ({
    mounted() {
        this.guide = guide;
        this.html = Vue.compile(`<p>Test</p>`).render;
        guide['add-location'].forEach(step => {
            this.$refs[step.ref].appendChild(this.html);
        })
    },
    data: function() {
        return {
            guide: null,
            html: null
        }
    }
});
export default Tutorial;

这就是我目前所拥有的,它正确地获得了ref,只是不能附加HTML,因为我认为我没有正确地使用Vue.compile

无法在"Node"上执行"appendChild":参数1的类型不是"Node">

在我看来,最好能避免直接对DOM进行变异。用v-html替换ref怎么样?

const tutorial = guide => ({
  mounted() {
    guide['add-location'].forEach(step => {
      this[step.ref] += this.html;
    })
  },
  data: function() {
    return {
      ...guide['add-location'].reduce((result, step) => {
        result[step.ref] = ''
        return result
      }, {}),
      html: `<p>Test</p>`
    }
  }
});
const Foo = {
  template: `
    <div>
      <div v-html='foo'></div>
      <div v-html='bar'></div>
    </div>
  `,
  mixins: [tutorial({
    'add-location': [
      { ref: 'foo' },
      { ref: 'bar' }
    ]
  })]
}

另一个想法是使用包装器组件来包装目标,或者如果您的目标是一个组件,那么您也可以创建一个作为mixin的包装器。

与html属性一起使用:

<wrapper ref='foo'>
  <div>Foo</div>
</wrapper>
const Wrapper = {
  props: ['html'],
  render(h) {
    return h('div', [this.$slots.default, h('div', {
      domProps: {
        innerHTML: this.html
      }
    })])
  }
}
...
this.$refs.foo.html = '<h1>Hello Foo</h1>'

示例

或者与自定义appendChild方法一起使用:

const Wrapper = {
  data: () => ({
    children: []
  }),
  methods: {
    appendChild(child) {
      this.children.push(child)
    }
  },
  render(h) {
    return h('div', [
      this.$slots.default,
      ...this.children.map(child => h('div', {
        domProps: {
          innerHTML: child
        }
      }))
    ])
  }
}
...
this.$refs.foo.appendChild('<h1>Hello Foo</h1>')
this.$refs.foo.appendChild('<h1>Hello Bar</h1>')

示例

或者在html不是普通html:的情况下与Vue.compile一起使用

const Wrapper = {
  data: () => ({
    template: '',
    context: {}
  }),
  methods: {
    setChild(template, context) {
      this.template = template
      this.context = context
    }
  },
  render(h) {
    let res = Vue.compile(this.template)
    return h('div', [
      this.$slots.default,
      h({
        data: () => this.context,
        render: res.render,
        staticRenderFns: res.staticRenderFns
      })
    ])
  }
}
...
this.$refs.foo.setChild('<h1>Hello {{ name }}</h1>', {
  name: 'Foo'
})

示例

最新更新