12
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Vue.js]bodyに直接appendする

Last updated at Posted at 2018-02-24

#概要

モーダルを使うときなど、しばしばrootのappの外側にコンポーネントを挿入したくなることがあります。
vueのツリー構造から外れるので、無理っぽいように一見思えるのですが、render関数と$forceUpdate関数を使うことで実現できます。

#デモ
https://jsfiddle.net/huigo/gdnwqzzu/

#コード

<div id="app">
  <h1>App</h1>
  <input type="text" v-model="message">
  <ul>
    <li v-for="item in list">{{item}}</li>
  </ul>
  <to-body>
    <div>
      <h1>to body</h1>
      <p>{{ message }}</p>
      <button @click="list.push('hello!')">
       Hello!
      </button>
    </div>
  </to-body>
</div>
Vue.component('to-body',{
  beforeCreate(){
    this._el = document.body.appendChild(document.createElement("div"));

    //bodyに挿入されるvmです。
    this._vm = new Vue({
      methods:{
        //<to-body>コンポーネントのslotを受け取って、再描画します。
        forseRender(slots){
          this._slots = slots;
          //もらってきたslotはこのvmが監視しているわけではないので、強制的に更新させます。
          this.$forceUpdate();
        }
      },
      render(createElement){
        if (this._slots){
          return createElement('div',this._slots);
        }
      }
    }).$mount(this._el);
  },
  render(createElement){
    //render関数が呼ばれたタイミングでbodyに挿入したvmを再描画させます。
    this._vm.forseRender(this.$slots.default);
  }
});
12
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?