わんすけに聞いてみる Web開発 [Vue.js]モーダルダイアログを表示してみる

[Vue.js]モーダルダイアログを表示してみる

以前の記事で、v-tooltipとタブレイアウトを組み合わせてスクリプト実行ライブラリに使えないかと模索してみたが、見え方がイマイチだったので今日はVue.jsでモーダルダイアログみたいな表示するやつ作ってみた。

ベースはここを参考に。
モーダルコンポーネントの例

 

1.コンポーネントを書いてみた。

モーダルでスクリプトの内容を表示します。

<template>
  <transition name="modal">
    <div class="modal-mask" v-on:click="$emit('close')">
      <div class="modal-wrapper">
        <div class="modal-container">
        <table>
        <tbody>
            <tr><th><h4>{{ title }}</h4></th></tr>
            <tr><td>
                <img v-if="imgflg" width="500" v-bind:src="link" />
            </td></tr>
            <tr><th>コード <input type='button' target="src_body" value="コピー" v-on:click="copy_content" /></th></tr>
            <tr><td><textarea id="src_body" class="small-font" rows="15" v-model="source"></textarea></td></tr>
            <tr><th>注釈 <input type='button' target="memo" value="コピー" v-on:click="copy_content"/></th></tr>
            <tr><td><textarea id="memo" class="small-font" rows="15" v-model="discript"></textarea></td></tr>
        </tbody>
        </table>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
module.exports = {
  props: {
    id: String,
    title: String,
    source: String,
    discript: String,
    link: String
  },
  computed: {
    imgflg() {
      let lnk = this.link;
      if(typeof lnk === "undefined") {
        return false;
      } else {
        return (lnk.slice(-4)==".png")?true:false;
      }
    }
  },
  methods:{
    copy_content: function(e){
      let tgt_id = e.target.getAttribute('target');
      document.getElementById(tgt_id).select();
      document.execCommand("Copy");
      alert('コピーしました。');
      e.stopPropagation();
    }
  }
}
</script>

<style>
.modal-mask {
  position: fixed;
  z-index: 9998;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, .5);
  display: table;
  transition: opacity .3s ease;
}
.modal-wrapper {
  display: table-cell;
  vertical-align: middle;
}
.modal-container {
  width: 600px;
  height: 100%;
  margin: 0px auto;
  padding: 20px 30px;
  background-color: #fff;
  border-radius: 2px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
  transition: all .3s ease;
  font-family: Helvetica, Arial, sans-serif;
  overflow-y: auto;
}
.modal-header h3 {
  margin-top: 0;
  color: #42b983;
}
.modal-body {
  margin: 20px 0;
}
.modal-default-button {
  float: right;
}
.modal-enter {
  opacity: 0;
}
.modal-leave-active {
  opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
  -webkit-transform: scale(1.1);
  transform: scale(1.1);
}
.align_right {
  text-align: right;
}
</style>

コンポーネント内部でのstyle定義だとモーダルの背景グレーが<style scoped>のままだとページ全体に反映されなかったのでscopedを外しました。
あと、.modal-containerが見切れてスクロールできなかったので、height: 100%; overflow-y: auto; を追加しました。
v-on:click="$emit('close')"をモーダル背景含む全体にして、コピーボタンのイベントでだけe.stopPropagation();させて、それ以外のどこかをクリックしたらモーダル画面が終了する様にしてみたり?

 

2.ページに実装する。

スクリプト実行ライブラリのページをモーダルダイアログ表示にしてみる。

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/http-vue-loader"></script>

<div id='main_menu'>
  <p>このページはIEでは動きません?</p>
  <div class="tbl-cell">
    <ul>
      <li v-for="item in items">
        <a href="#" class="small-font" v-on:click.prevent="detail_load" v-bind:id="item.id">{{ item.title }}</a>
      </li>
    </ul>
    <ModalTable  v-if="showModal" @close="showModal = false" v-bind="current" />
  </div>
</div>

<script type="text/javascript">
<!--
var app = new Vue({
  el: "#main_menu",
  data: {
      items: [{ title: "読み込み中。。。" }],
      current: {},
      showModal: false,
      state: "init",
      err: null,
      errored: null
    },
  components: {
    'modaltable': httpVueLoader('https://yizm.work/script/vue_mdl/ModalTable.vue')
  },
  created: function (){ 
      axios.get('https://yizm.work/ajax/source_ajax.php', { params: {type: "index", category: "winactor"} })
      .then(response => {
        this.items = response.data
      }).catch(err => {
        (this.errored = true), (this.error = err);
      }).finally(() => (this.state = "finally" ));
    },
  methods:{
    detail_load: function(e){
      let rec_id = e.target.getAttribute('id');
      axios.get('https://yizm.work/ajax/source_ajax.php', { params: {type: "detail", category: "winactor", id: rec_id } })
      .then(response => {
        let d = response.data[0];
        this.current = { id:d["id"], title:d["title"], source:d["source"], discript:d["discript"], link:d["link"] }
        this.showModal = true;
      }).catch(err => {
        (this.errored = true), (this.error = err);
      }).finally(() => (this.state = "finally" ));      
    }
  }
});
-->
</script>

すると、こんな感じになると。




 

ちょっとイイ感じかもしれない?

あとね、ちょっとしたエディタ機能を添えたいんだよねー?

コピペしながらリファレンス読むときって、メモ帳めっちゃ使っちゃうから。。。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Related Post