質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.60%

vue.js methodsのつかい方について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 654

holic

score 119

 前提・実現したいこと

metodsの使い方について疑問が出てきたので投稿させてください。
やりたかったことはマウスオーバー、マウスアウトで背景画像がチェンジするという簡単なシステムを作っていました。
まずはソースを記します。

cssは本題と関係ないと思いますので、省きます。⇒追記しました。

 該当のソースコード

<script src="./js/vue.js"></script>
<body>

            <div class="wrap bg_jiyu" id="jiyu_bg">
                <div id="jiyu_area">
                    <div class="inner">
                        <ul class="bt_area">
                            <li><a @mouseover="bgChenge($event)" @mouseout="bgAlways" value="cov01" href="javascript:void(0)">ボタンその1</a></li>
                            <li><a @mouseover="bgChenge($event)" @mouseout="bgAlways" value="cov02" href="javascript:void(0)">ボタンその2</a></li>
                            <li><a @mouseover="bgChenge($event)" @mouseout="bgAlways" value="cov03" href="javascript:void(0)">ボタンその3</a></li>
                        </ul>
                    </div>
                </div>
                <i class="cov_always"></i>
                <transition name="fade">
                    <i v-if="currentCheck('cov01')" class="cov01" key="cov01"></i>
                    <i v-if="currentCheck('cov02')" class="cov02" key="cov02"></i>
                    <i v-if="currentCheck('cov03')" class="cov03" key="cov03"></i>
                </transition>
            </div><!-- / .wrap -->
    </div>
    <!-- / .main-continer -->
    <script>
        let jiyu_bg = new Vue({
            el: '#jiyu_bg',
            data: function () {
                return {
                    msg: '',
                    currentBg: null
                }
            },
            methods: {
                bgChenge: function (event) {
                    this.currentBg = event.target.attributes.value.value;
                    //console.log(event.target.attributes.value.value);
                },
                bgAlways: function () {
                    this.currentBg = null;
                },
                currentCheck: function (name) {
                    return this.currentBg === name;
                }
            }
        })
    </script>
</body>
    .bg_jiyu {
        position: relative;
        z-index: 1;
    }

    .bg_jiyu [class^=cov] {
        /* display: none; */
        width: 100%;
        height: 100%;
        position: absolute;
        top: 0;
        left: 0;
        z-index: -2;
        background-size: cover;
    }

    .bg_jiyu i.cov_always {
        background-image: url(images/jiyubg00.jpg);
    }

    /* .bg_jiyu [class^=cov] {
        display: none;
    } */

    .bg_jiyu i.cov1 {
        background-image: url(images/jiyubg01.jpg);
    }

    .bg_jiyu i.cov2 {
        background-image: url(images/jiyubg02.jpg);
    }

    .bg_jiyu i.cov3 {
        background-image: url(images/jiyubg03.jpg);
    }

    .bt_area {
        position: static;
        z-index: 10;
        height: 500px;
        display: flex;
        justify-content: space-between;
        align-items: flex-end;
        padding-bottom: 40px;
    }

    .bt_area li a {
        border: 3px solid #fff;
        color: #fff;
        font-size: 3.0rem;
        font-weight: bold;
        padding: 20px 30px;
        transition: 0.4s;
    }

    @media screen and (max-width: 640px) {
        .bt_area {
            flex-direction: column;
            justify-content: flex-end;
            align-items: center;
        }

        .bt_area li {
            width: 100%;
        }

        .bt_area li a {
            display: block;
            padding: 10px 15px;
            margin-bottom: 10px;
            font-size: 1.4rem;
            text-align: center;
        }
    }

    .bt_area li a:hover {
        background-color: rgba(251, 251, 251, 0.7);
    }

    /*transition設定*/
    .fade-enter-active,
    .fade-leave-active {
        transition: all 0.5s ease;
    }

    /* 表示される時は0から1へ*/
    .fade-enter {
        opacity: 0;
    }

    .fade-enter-to {
        opacity: 1;
    }

    /* 消える時は1から0へ*/
    .fade-leave {
        opacity: 1;
    }

    .fade-leave-to {
        opacity: 0;
    }

 分からないところ

上記ソースで目的とする挙動はなんとか出来ておりました、
vue.jsの理解を深めたいためにお聞きしたいです。

その①
メソッド「currentCheck」が発動するのはどうしてでしょうか。
メソッドに3つ登録しました、「bgChenge」「bgAlways」「currentCheck」です。
わたしの理解では、メソッドに登録されているものはイベントがなければ発動しないと思ってました、
「bgChenge」は@mouseoverにより発動します。
「bgAlways」は@mouseoutにより発動します。
上記二つはもちろん理解できました、
しかし「currentCheck」はとくにイベントがないのにもかかわらず、発動します。

currentBgの値が変化することにより発動している?
computedに登録したならば、function記述の中に対応するdata値が存在し、それが変動しているならば発動すると理解してました、
まさしくこの動きをmethodsに登録したものがしてくれております。
これはどうしてでしょうか。

その②

<i v-if="currentCheck('cov01')" class="cov01" key="cov01"></i>
<i v-if="currentCheck('cov02')" class="cov02" key="cov02"></i>
<i v-if="currentCheck('cov03')" class="cov03" key="cov03"></i>


上記の記述ですが、『cov01』ばかりになってしまって、あまりスマートには見えません。
他のattr要素(classやkey)にも同じ値が入っているので、attr要素の値を使うことはできないのでしょうか。
以下のような感じです。

<i v-if="currentCheck()" class="cov01" key="cov01"></i>
<i v-if="currentCheck()" class="cov02" key="cov02"></i>
<i v-if="currentCheck()" class="cov03" key="cov03"></i>


お手数ではございますが、ただいま、javascript,vueの勉強中でございます、
今後の理解のためにもご教示をお願いします。

 補足情報(FW/ツールのバージョンなど)

vue:2.5.2

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

ReactやVueといった最近のUI frameworkはそのdeclarative(宣言的)な性質が便利だということで人気がでています。「どのように」DOMを操作するかは気にせず、「何を」表示するかを指定するだけでよく、また state (Vue ではdataのこと) が変わると自動的に表示が更新される、つまり reactive であるというのも特徴です。

「currentCheck」はとくにイベントがないのにもかかわらず、発動します。

v-if="currentCheck('cov01')"と書いているので、Vueはこの currentCheck('cov01') という expression を実行して該当の要素を表示するかどうかを決定するからです。

Vue はこの currentCheckという method が currentBg に依存しているというのをわかっているので、currentBgの値が変更されると rendering が発生して、再びcurrentCheckが実行されて表示が更新されます。

他のattr要素(classやkey)にも同じ値が入っているので、attr要素の値を使うことはできないのでしょうか。

attr要素ではなくattributeのことだと思いますが、そのようなまわりくどいことは普通しません。
今の場合同じような要素を並列に並べているので、v-forを使うのがいいです。そうすれば、v-forの変数から、今欲しい値('cov**')が作れます。

↓ここもattribute から値を取得してしまっていますが、上と同様の方法でやるのがいいです。

                bgChenge: function (event) {
                    this.currentBg = event.target.attributes.value.value;
                    //console.log(event.target.attributes.value.value);
                },

今の場合、currentBgは string "cov**"である必要はなく、単に整数値(1,2,3)でいいと思います。あと mouseover ではなく mouseenter でいいと思います。

                bgChenge: function (i) {
                    this.currentBg = i
                },
...
<li v-for="i in 3"><a @mouseenter="bgChenge(i)" @mouseout="bgAlways" href="javascript:void(0)">ボタンその{{i}}</a></li>
...
<i v-for="i in 3" v-if="currentCheck(i)" :class="'cov' + i" :key="i"></i>
...

このコードだと class は cov01 ではなく cov1 という形になってるので注意してください。

JSFiddle Demo

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/27 02:57

    Vue がどのように state の変化を検知するかはここで解説されてます。
    英語
    https://vuejs.org/v2/guide/reactivity.html
    日本語
    https://jp.vuejs.org/v2/guide/reactivity.html

    キャンセル

  • 2018/10/27 10:48 編集

    Karamarimo様
    的確なご回答ありがとうございます。すっきりとしました。
    上記お知らせしていただいたvue公式記事からも、メソッドである「currentCheck」とプロパティである「currentBg」が依存関係にあるとよく理解しました。

    デモページも作成していただきましてありがとうございます、cssの部分は想像で書いていただきまして失礼しました、私のcssも追記いたしました。
    ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る