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

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

新規登録して質問してみよう
ただいま回答率
85.50%
ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

Vue.js

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

JavaScript

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

Q&A

解決済

2回答

409閲覧

Error in directive my-directive bind hook | vue.js

ruuusaamarki

総合スコア468

ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

Vue.js

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

JavaScript

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

0グッド

0クリップ

投稿2019/02/04 05:00

前提・実現したいこと

書籍のvuejsのディレクティブサンプルコードが動かない状態です。

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

デベロッパーツールのコンソールに表示されるエラーになります。

[Vue warn]: Error in directive my-directive bind hook: "TypeError: Cannot set property 'innerHTML' of undefined" vue.js:1841 TypeError: Cannot set property 'innerHTML' of undefined

フォームに入力してクリックをすると以下の部分が増えていきます。

[Vue warn]: Error in directive my-directive bind hook: "TypeError: Cannot set property 'innerHTML' of undefined"

該当のソースコード

directive.js

1Vue.directive('my-directive', { 2 bind: function(){ 3 this.el.innerHTML = '<p>**bind now**</p>'; 4 }, 5 update: function (newValue, oldValue) { 6 this.el.innerHTML = '<p>' + oldValue + ' → ' + newValue + '</p>'; 7 }, 8 unbind: function(){ 9 this.el.innerHTML = '<p>**unbind**</p>'; 10 }, 11}); 12 13function initial(){ 14 15 new Vue({ 16 el: '#msg', 17 data: { 18 val:'', 19 message:'this is message!' 20 }, 21 methods: { 22 myfunc:function() { 23 this.message = this.val; 24 } 25 } 26 }); 27}

directive.html

1<!doctype html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" 6 content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>vue-lessons</title> 9 <script src="https://npmcdn.com/vue/dist/vue.js"></script> 10 <script src="js4-36.js"></script> 11 <link rel="stylesheet" href="style.css"> 12</head> 13<body onload="initial();"> 14<h1>Vue.js</h1> 15<div id="msg"> 16 17 <div v-my-directive="message">ok.</div> 18 19 <input type="text" v-model="val"> 20 <input type="button" v-on:click="myfunc();" value="click"> 21</div> 22</body> 23</html>

試したこと1

this.el.innerHTMLをthis.elとしてみたら
デベロッパーツールのエラーは消え、ideでもelの部分が紫になりましたが
DOM要素が書き変わるという動作はしませんでした。

試したこと2

<div v-my-directive="message">ok.</div> ↓ <div v-my-directive="message"><p>ok.</p></div>

としてみましたが変化ありませんでした。

他に試すべきことなどご教授いただけましたら幸いです。
よろしくお願いいたします。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2019/02/05 05:09 編集

参考にしている書籍名・章・ページ数も合わせて記述していただけると、切り分けがしやすくなると思います。また、どのような状態を期待するか記述があると、こちらでも検証しやすいです????
7Kreuz

2019/02/05 07:13

ソースコードを見るとvue1.0の書き方ですが、vue2.xを使用していませんか?
ruuusaamarki

2019/02/05 12:46

MofuMofu2さん、コメントありがとうございます。書籍はjavascriptフレームワーク入門というもので、chapter4のP151、152に掲載されているサンプルになります。ディレクティブを使用してinputに入力したものをpタグとして出力するという内容になります。何かお心当たりがありましたらよろしくお願いいたします。
ruuusaamarki

2019/02/05 12:48

7Kreuzさん、コメントありがとうございます。おっしゃる通りhttps://npmcdn.com/vue/dist/vue.jsを使用しており2を使用しておりました。少し自分でも調べてみます。ありがとうございます。
退会済みユーザー

退会済みユーザー

2019/02/05 12:58

なるほど、ありがとうございます。2016年発刊なので、本の内容と今のVueは書き方が大きく変わってしまっていますね…。ちなみにVueは2系で動作させる想定ですか?
ruuusaamarki

2019/02/05 13:44

はい、2系で動作させたいと思います。今こちらのページhttps://jp.vuejs.org/v2/guide/custom-directive.htmlと vue.js入門という書籍のカスタムディレクティブの項目をみていたのですが苦戦しています ^^;
guest

回答2

0

ベストアンサー

とりあえず、Vue2.xでのカスタムディレクティブの書き方に合わせると、次のようになると思います。

Vue.directive('my-directive', { bind: function(el){ el.innerHTML = '<p>**bind now**</p>'; }, update: function (el, {value, oldValue}) { el.innerHTML = '<p>' + oldValue + ' → ' + value + '</p>'; }, unbind: function(el){ el.innerHTML = '<p>**unbind**</p>'; } });

投稿2019/02/07 00:00

編集2019/02/07 00:26
7Kreuz

総合スコア112

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

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

ruuusaamarki

2019/02/07 02:01

7Kreuzさんご回答ありがとうございます。ご教授いただきましたコードで2系でも動作させることができました!elの参照の仕方もそうですがカスタムディレクティブ自体の守備範囲も変わってきているようでした。 https://jp.vuejs.org/v2/guide/migration.html#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96-%E5%8D%98%E7%B4%94%E5%8C%96 1系から2系で色々と変更があったようですね。しかしvueは慣れればかなり便利そうな感触は掴めました。導入コストも割とスムーズに入れるのも評判通りでもう少しこのまま勉強してみたいと思います。今回は色々と勉強になりました。ありがとうございましたm(_)m
guest

0

同じ本を読んだ方の感想から内容を推察しての回答となりますが…。
Vue.jsのv-modelを利用して、<input>タグ内に表示されたテキストを<p>タグに表示することをやりたいのかなと思いました。

まずはじめに、コード例を示します。Vue.jsはCDN配信のものを利用しています。
v-modelを使った双方向データバインディングの例も合わせて参照してみてください。実際に動かすことが可能です。

html

1<!DOCTYPE html> 2<html lang="ja"> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue.js App</title> 6 <link href="textboxSample.css" rel="stylesheet"> 7 <link href="https://fonts.googleapis.com/css?family=Varela+Round" rel="stylesheet"> 8 </head> 9 <body> 10 <header> 11 <div class="header-text">Vue.js CDN Sample App</div> 12 </header> 13 <div id="app"> 14 <div class="message-box"> 15 <div class="message">Enter some messages.</div> 16 <input type="text" class="text-box" v-model="textVal"> 17 <p>{{ textVal }}</p> 18 </div> 19 </div> 20 <script src="https://cdn.jsdelivr.net/npm/vue@2.6.0/dist/vue.js"></script> 21 <script src="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.css"></script> 22 <script src="textboxSample.js"></script> 23 </body> 24</html>

javascript

1var app = new Vue({ 2 el: '#app', 3 data() { 4 return { 5 textVal: '' 6 } 7 } 8})

実装後の画面

結論からいうと、<p>{{ val }}</p>の記載がHTML上に存在しないため、データバインディングの値が画面に表示されないのかと思います。

コードを比較していただくとわかりますが、Vue.jsの記述方法を再度見直した方が良いかもしれません。

まず、HTML側の書き方から見てみましょう。

html

1 <script src="https://npmcdn.com/vue/dist/vue.js"></script>

Vue.jsをCDN形式で読み込むときは、公式ドキュメントの<script>-直接組み込みを参照して読み込みを行いましょう。

具体的なサンプルコードが知りたいときは基礎から学ぶVue.jsのサポートページ Chapter1を参考にするとわかりやすいでしょう。こちらの本はかなり丁寧な解説がされているのと、Web上のサポートページが親切です。初めて学ぶときは「基礎から学ぶVue.js」を参照されることをおすすめします。

html

1<div id="msg"> 2 3 <div v-my-directive="message">ok.</div> 4

念のための確認ですがVue.jsであっても、classを作りたいときはHTMLと同じように記述します。コンポーネント部分を記述するときは<コンポーネント名></コンポーネント名>で記述します。今回の例だと<div class="message">ok.</div>という風に記述します。

html

1 <input type="text" v-model="val">

v-modelは「テキストボックスに入力したデータをリアルタイムに画面へ描画したい」といった要件を実現するときに使用します。今回の要件はこれに近いので、記載いただいているようにv-modelを利用すると良さそうです。公式ドキュメントではフォーム入力バインディングの項が該当します。

しかし、いただいたHTMLをみるとv-modelで持っている値"val"を表示するHTMLタグが見当たりません。私のサンプルではtextValという値がpタグに出てきているかと思います。この部分を記述しなければ、v-modelで取得した値を表示することはできません。Vue.jsではデータの値をHTMLへ描画するときに{{ 変数名 }}という記法を利用します。

html

1 <input type="button" v-on:click="myfunc();" value="click">

clickイベントを押すとmyfuncという名前のメソッドを実行したいのかと思いました。今回の要件はv-modelだけで実現できてしまいそうなので不要かなと思ったのですが、記述方法が間違っているので動かないようです。公式ドキュメントを確認してみてほしいのですが、v-on:clickの後はメソッド名のみ記述します。

html

1 <input type="button" v-on:click="myfunc">

続いてJS側の処理です。

javascript

1Vue.directive('my-directive', { 2 bind: function(){ 3 this.el.innerHTML = '<p>**bind now**</p>'; 4 }, 5 update: function (newValue, oldValue) { 6 this.el.innerHTML = '<p>' + oldValue + ' → ' + newValue + '</p>'; 7 }, 8 unbind: function(){ 9 this.el.innerHTML = '<p>**unbind**</p>'; 10 }, 11}); 12

この部分は要件がわからなかったので何とも言えないのですが、v-modelでデータバインディングしたものを表示するだけであれば不要です。

javascript

1function initial(){ 2 3 new Vue({ 4 el: '#msg', 5 data: { 6 val:'', 7 message:'this is message!' 8 }, 9 methods: { 10 myfunc:function() { 11 this.message = this.val; 12 } 13 } 14 }); 15}

function initial()の部分は不要です。代わりにnew Vueの前に変数宣言が必要です。記述方法ははじめにの項を参照されると良いでしょう。

data部は記載いただいているように、valに空白のデータを割り当てておくようにします。

やりたいことに沿っているかわかりませんが、回答になったでしょうか。
はじめはVue.jsの公式ドキュメントを参照しつつ、小さく作って動かしていくことをおすすめします。
また、実現したいことを整理して、それに合わせて利用する記法を選択することも重要です。

投稿2019/02/06 03:29

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

7Kreuz

2019/02/07 00:10

> Vue.jsのv-modelを利用して、<input>タグ内に表示されたテキストを<p>タグに表示することをやりたいのかなと思いました。 たぶん違う……と思います。ruuusaamarkiさんはたぶんすでにできます。 > この部分は要件がわからなかったので何とも言えない おそらくこの部分が要件の核心で、「ボタンを押すたびに、div内に『(前の値)→(今の値)』と表示させる」ということがしたいのだと思います。これ自体にカスタムディレクティブ必須というわけではない気もしますが、練習ということでチャレンジしていたものかと。
退会済みユーザー

退会済みユーザー

2019/02/07 00:42

なるほど…!その考えは思いつかなかったです…。私も推察力が足りてないですね、勉強します????
ruuusaamarki

2019/02/07 01:08

7Kreuzさん、コメントありがとうございます。私の説明力をフォローしていただきありがとうございますm(_)mまさしくおっしゃる通りの動きのサンプルでした。画像を最初から貼るべきでした。
ruuusaamarki

2019/02/07 01:30 編集

MofuMofu2さん、詳細なご回答ありがとうございます。私の知らない情報もあり、直接読み込みのところを参考にさせていただき、githubのvuejsのリリースノートを確認して発売前後のバージョンで試したところvue1系では動作させることができました。また今回のサンプルのbind,unbindはなくても動作するとのことが書籍に書いてありました。私の確認不足でそのまま載せてしまいました。おそらく、筆者の方がこれらフックの動きを確認できるようにと配慮してくださったのだと思います。私の説明が不足しており申し訳ありませんでしたm(_)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問