ryota21silvaの技術ブログ

Funna(ふんな)の技術ブログ

これまで学んだ技術の備忘録。未来の自分が救われることを信じて

【超Vue.js】Vueインスタンスとその内部構造はこうなっている【セクション4 】

50. イントロダクション

Vueインスタンス

Vueインスタンスって複数作れるの?他のjsからアクセスできるの?とかの内容

51. Vue インスタンスは複数作ることができる

Vueインスタンスはなるべく複数使用しない方がいい

完全に独立してるなら使ってもおk。
#app2押すと、#app1に何らかの処理が起きるとかはやめよう。そのような処理は一つのインスタンスの中(#app1の中)にまとめる。

52. 外側からVue インスタンスにアクセスする方法

<div id="app1">
  <p>{<200c>{ message }}</p>
</div>
<div id="app2">
  <p>{<200c>{ message }}</p>
  <button @click="changeMessage1">変更</button>
</div>
 
// 変数を設定
var vm1 = new Vue({
    el: '#app1',
  data: {
    message: 'インスタンス1'
  }
})
 
// 変数を設定
var vm2 = new Vue({
    el: '#app2',
  data: {
    message: 'インスタンス2'
  },
  methods: {
    changeMessage1: function() {
        // #app2から#app1のインスタンスにアクセス
        vm1.message = 'インスタンス2からアクセスして変更しました'
    }
  }
})

53. リアクティブシステム(getter、setter、Watcher)がどのように動いているかを確認し、プロパティを後から追加できないことを理解する

外部から新しいプロパティの追加はできない

厳密に言うとリアクティブにならない

リアクティブVue側のデータが変わると、HTMLのデータも変わる(ブラウザの表示が変わる)。これはvueがやってくれている。

リアクティブになる理由

まずインスタンス内のdataに、リアクティブにしたいプロパティを最初に置いておく。以下ではmessage

Vue.jsがやってくれることは、インスタンスのプロパティウォッチャを作ってくれる(=getterとsetterを用意してくれる)

getter...その変数(プロパティ)が参照された時に、関数を実行する setter...その変数(プロパティ)が変更された(書き換わった)時に、関数を実行する。
ウォッチャとは...getter,setterをトリガーに関数を実行してくれる。

var vm = new Vue({
    el: '#app',
  data: {
    message: 'こんにちは'
  }
})
 
// インスタンス生成後に、インスタンスの外部から後付けで作ったプロパティ
vm.name = 'よしぴー'
 
console.log(vm);

上記を書いてconsoleをみてみると、以下がある。

get message: ƒ proxyGetter()
set message: ƒ proxySetter(val)

→これがあるから、リアクティブになる!!

一方で、外部から作ったプロパティvm.nameにはgetterとsetterがない、つまり、clickイベントで値を変えようとしても変わらないのです。

54. Vueインスタンスプロパティの$dataの紹介

Vueインスタンスが使えるようなメソッドは$メソッドという形になっている。

外部のデータを、インスタンス内にセットすることはできる。
// 外部のデータ
var data = {
 message: 'こんにちは'
}
 
var vm = new Vue({
 el: '#app',
 // valueに上記の変数dataを入れている
 data: data
})
 
console.log(data === vm.$data);
console.log(vm);

55. インスタンスの内側から、Vueインスタンスのプロパティやメソッドにアクセスする

内部からはthis

var data = {
    message: 'こんにちは'
}
 
var vm = new Vue({
    el: '#app',
   data: data,
    computed: {
      myData: function() {
            return this.$data;
                  }
            }
})

56. VueのAPI一覧はここに載っています。

Vueインスタンスのプロパティやメソッドはどう使うのかなあ
→公式のAPI一覧を見よう!!

57. $mountメソッドを使用して、elプロパティの代わりにする

$mount

たまに使う。elプロパティの代わりになる

// まだインスタンス内で、elで指定していない
var vm = new Vue({
  data: data,
  computed: {
    myData: function() {
        return this.$data;
    }
  }
})
// ビューテンプレートを指定している(マウントしている)
vm.$mount('#app')

58. templateプロパティを使って、文字列のみでテンプレートを書く

テンプレートの書き方は3種類ある

1. 普通の書き方

<p>{<200c>{ message }}</p>
<button @click="message = 'ボタンから変更'">変更</button>

2. templateプロパティ(この書き方は複数行あると大変)

<div id="app2"></div>
 
new Vue({
  el: '#app2',
  data: {
    name: 'りょうた'
  },
  // teplateプロパティの値に、そのまま全部文字列として入れる
  template: '<p>こんにちは、{<200c>{ name }}</p>'
})

$mountを末尾に付けても同じように書ける

new Vue({
  data: {
    name: 'りょうた'
  },
  template: '<p>こんにちは、{<200c>{ name }}</p>'
}).$mount('#app2')

3. render関数(次回)

59. render(描画)関数を使用して、仮想ノードを作ってDOMの描画を行う

render関数

createElementはデフォルトで使える

<div id="app3"></div>

new Vue({
  data: {
  name: 'りょうた'
  },
  render: function(createElement) {
  // createElementはメソッドになっている
  return createElement('h1', 'こんにちは' + this.name);
  },
}).$mount('#app3')

以下のようにhで書くことも多い

render: function(h) {
  return h('h1', 'こんにちは' + this.name);

上記はdocument.createElementのcreateElementとは全くの別物

DOM

var dir = document.createElement('div');
console.log(dir);
console.log(document);
console.dir(document);

documentはdocument(=ブラウザ)がHTMLを受け取ってDOMに変換してオブジェクトにしてくれる。
objectはキーと値
modelは形
DOMを読み取ってHTMLぽく表示してくれる

return createElement('h1', 'こんにちは' + this.name)は仮想Nodeを作っている。
→VNodeは仮想Node→オブジェクト(ただの情報=文字列)を返している
→DOMを触っていない
→仮想DOMを作る
f:id:ryota21silva:20200630224142p:plain

document.createElement('div');は直接DOMにアクセスしている f:id:ryota21silva:20200630224156p:plain

仮想DOMと、その必要性を理解する

仮想DOMを作るために仮想Nodeを返す

仮想DOM...DOM要素を模したJS用のオブジェクト

何故使う?

ボタンを推した時に表示が変わるようにする
→変更する時に、部分的にDOMを使うのが効率良い
→DOMを一回作って、新しく作ったDOMと見比べて、変更がある箇所(差分)だけ変える、この新しいDOMを作るのがめっちゃ効率悪い。
→仮想的なDOM(自分のjsで仮想的なDOMオブジェクト)を作って、前の仮想DOMと見比べて変更する。効率が良い。

普通のDOM

DOMにアクセスして、追加、削除、変更とかするからめっちゃ遅い。パフォーマンス悪い。
普通のDOMはブラウザにあるから(documentとか)、DOMにアクセスする=ブラウザにアクセスするから遅い

62. Vue インスタンスライフサイクルの全体像を見て、Vueがどのように動いているかを理解する

ライフサイクル

Vuejsが作られてから、どのような動きをして〜までの流れ。

  1. new Vue()...beforeCreate()
  2. インスタンスが作られる(データがリアクティブになる)...created() (elがあるかどうか)
  3. ある場合、templateをrender関数にコンパイル(ない場合、vm.$mountが呼ばれた時に、templateをrender関数にコンパイル)
  4. $elを作って実際のDOMに追加
  5. mounted(⇄データが変わるとDOMを再描画)
  6. Destroyed(手動でやることは基本ない)

63. ライフサイクルフックのタイミングを実際にコードで確かめる

<div id="app4">
  <p>こんにちは、{<200c>{name}}</p>
  <button @click="name = '太郎'">名前変更</button>
  <button @click="destroy">インスタンスを破壊</button>
</div>
 
new Vue({
  el: '#app4',
  data: {
    name: 'りょうた'
  },
  beforeCreate: function() {
    console.log('beforeCreate');
  },
  created: function() {
    console.log('Created');
  },
  beforeMount: function() {
    console.log('beforeMount');
  },
  mounted: function() {
    console.log('mounted');
  },
  beforeUpdate: function() {
    console.log('beforeUpdate');
  },
  updated: function() {
    console.log('updated');
  },
  beforeDestroy: function() {
    console.log('beforeDestroy');
  },
  destroyed: function() {
    console.log('destroyed');
  },
  methods: {
    destroy: function() {
        this.$destroy()
    }
  }
})

64. コンポーネントを使用して、同じようなインスタンスを使い回す

コンポーネントを登録した後に、インスタンスで使う

Vue.component('hello', {
  template: '<h1>こんにちは</h1>'
});
<div id="app">
  <hello></hello>
  <hello></hello>
</div>
 
var data = {
    message: 'こんにちは'
}
 
Vue.component('hello', {
  template: '<h1>こんにちは</h1>'
});
 
var vm = new Vue({
  data: data,
  computed: {
    myData: function() {
        return this.$data;
    }
  }
})
 
vm.$mount('#app')