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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

3521閲覧

Vue.jsのv-on:clickを使ってサムネイルクリックでメイン画像を切り替えたいです。

fungi

総合スコア2

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2021/10/03 23:51

編集2021/10/04 06:14

前提・実現したいこと

ウィンドウの伸び縮みで横に並ぶ数が変わるサムネイルクリックでメイン画像を切り替えるのをVue.jsのv-on:clickで適用したいです。

Win10・GoogleChromで確認しています。

発生している問題・エラーメッセージ

まず、サムネイルのクリックしたものとクリックしていないものの違いを出すために、「activ」というclassをimg要素に適用させようとしましたが、クリックするたびにすべてactivが生き残ってしまいます。

次に、onclickで関数を適用させるとメイン画像が切り替わるようにできたのですが、Vue.jsのmethodsで作った関数をv-on:clickで適用すると何も反応しなくなりました。
Vue.jsにこだわっているわけではないのですが、何がいけないのか分かりません。

該当のソースコード

html

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <title >test</title> 7 <link rel="stylesheet" type="text/css" href="test.css" /> 8 <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> 9 <script src="test.js" defer></script> 10</head> 11 12<body> 13 14 <div id="app"> 15 16 <div id="content"> 17 <img id="img" src="img/01.JPG"> 18 </div> 19 20 <div id="thumb_img"> 21<!--↓ウィンドウの幅によって横並びになる枚数を変えるために<div class="thumb">をつけました。--> 22 <div class="thumb"><img class="active" src="img/01.JPG" v-on:click="changeimg('img/01.JPG',this)"></div> 23 <div class="thumb"><img src="img/02.JPG" v-on:click="changeimg('img/02.JPG',this)"></div> 24 <div class="thumb"><img src="img/03.JPG" v-on:click="changeimg('img/03.JPG',this)"></div> 25 </div> 26 27 </div> 28</div> 29</div> 30</body> 31</html>

css

1#content { 2 width: 650px; 3 height: 320px; 4 margin: 10px; 5 text-align: center; 6} 7 8#content img{ 9 object-fit: contain; 10 width: 100%; 11 height: 100%;} 12 13#thumb_img { 14 width: 650px; 15 display: flex; 16 flex-wrap: wrap; 17 padding: 5px; 18 justify-content: center; 19 background-color: rgb(206, 207, 204);} 20 21 .thumb{ 22 width: 100px; 23 height: 100px; 24 margin: 10px; 25 cursor: pointer;} 26 27 .thumb img { 28 object-fit: cover; 29 width: 100%; 30 height: 100%;} 31 32 .active{ 33 border:5px solid #fff;}/*選択していることが分かるように枠を付けたいです。 34

javascript

1new Vue({ 2 el: "#app", 3 4 methods: { 5 changeimg: function(a,b) { 6 document.getElementById("img").src = a 7 8 let nodes = document.getElementById("thumb_img") 9 let img_thumb = nodes.children; 10 for (i = 0; i < img_thumb.length; i++){ img_thumb[i].classList.remove("active") } 11    //↑ここでactiveが消えて↓でクリック箇所だけ再度activを入れたいです。 12 b.classList.add("active") 13 14 } 15 } 16}) 17

試したこと

Vue.jsから抜いて、↓の関数をonclicで適用するとメイン画像の切り替えはできました。

javascript

1function changeimg(a,b) { 2 document.getElementById("img").src = a 3 4 let nodes = document.getElementById("thumb_img") 5 console.log(nodes)//※ここで一度コンソールに出力してみました。 6 let img_thumb = nodes.children; 7 for (i = 0; i < img_thumb.length; i++){ img_thumb[i].classList.remove("active") } 8 b.classList.add("active")}

※でコンソール出力するとこのように表示されました。
イメージ説明
クリックでactiveが消えないのは、入れ子になっているからでしょうか?

追記

HTMLの</div>の位置が変なところになったので直しました。

画像クリックのときのエラーは以下のようにでます。
イメージ説明

クリックでclassのactiveをすべて消して、クリック箇所にactiveを再付与は以下のように書き替えたらできましたが、Vue.jsではエラーになってしまいます。

javascript

1let nodes = document.getElementsByClassName("thumb") 2for (i = 0; i < nodes.length; i++){ nodes[i].children[0].classList.remove("active") } 3b.classList.add("active")

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

なんかもったいないvueの使い方な気がする…
vue使えば基本getElementByIdとかしなくてもかけるからだいぶ簡単に書けるはず。

というかタグ変じゃない?#appが一瞬で閉じられている気がする。
vueインスタンスのdataにバインドしてくれるんだから使わない手はない。

classも例えば「v-on:class="{active : 式}"」みたいに書けば
式がtrueの時にclass="active"みたいな感じにもできるし
imgのsrcも変数で持たせることもできる。
(「:src」とか「:class」はそれぞれ「v-on:src」、「v-on:class」の省略記法)
v-forで配列回して色々すればどんどんhtmlもイベントも省略できます。
@click="select = idx"とすればchangeimgメソッドも不要に…。

https://jsfiddle.net/8gumes4x/

html

1 <div id="app"> 2 <div id="content"> 3 <img id="img" :src="imgs[select].src"> 4 </div> 5 6 <div id="thumb_img"> 7 <div class="thumb" v-for="(img,idx) in imgs "> 8 <img :class="{active : select == idx}" :src="img.src" @click="changeimg(idx)"> 9 </div> 10 </div> 11 12 </div>

javascript

1var app = new Vue({ 2 el: "#app", 3 data: { 4 select: 0, 5 imgs: [{ 6 src: "img/01.JPG" 7 }, 8 { 9 src: "img/02.JPG" 10 }, 11 { 12 src: "img/03.JPG" 13 }, 14 ] 15 }, 16 methods: { 17 changeimg: function(index) { 18 this.select = index 19 } 20 } 21})

投稿2021/10/04 08:11

sousuke

総合スコア3828

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fungi

2021/10/04 08:44

ご教示ありがとうございます。 こんなにシンプルになるなんて…。大変勉強になりました。 this.selectで「0」が入ることもしりませんでしたので、「select == idx」のように比較して判定する形にも辿り着けませんでした…。 本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問