JavaScript

Vue.js お勉強だよ

Vue.js

 

お勉強用リポジトリ
https://github.com/yuukanehiro/Vue-Study

Udemyと参考書をやってみてメモ

 

きほんのき

はろわ!

hello.html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>Vue.js</title>
</head>
<body>
<div id="app">
    <p>{{ message }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="js/hello.js"></script>
</body>
</html>

 

js/hello.js

let app = new Vue({
    el: '#app',
    data: {
        message: 'はろわ!'
    }
})

 

v-bind

bind.html

    <div id="app">
        <a v-bind:href="url">優技録</a>
    </div>

 

js/bind.js

let app = new Vue({
    el: '#app',
    data: {
        url: 'https://www.yuulinux.tokyo'
    }
})

 

v-model 双方向データバインディング

 

vmodel.html

    <div id="app">
        <input type="text" v-model="data">
        <p>{{ data }}</p>
    </div>

 

js/vmodel.js

let app = new Vue({
    el: '#app',
    data: {
        data: '優技録だよ',
    }
})

 

 

computed

 

computed.html

<div id="app">
    <p>{{ localEmail }}</p>
</div>

 

js/computed.js

let app = new Vue({
    el: '#app',
    data: {
        email: 'YUU3@example.net'
    },
    computed: {
        localEmail: function() {
            return this.email.split('@')[0].toLowerCase() + '@' +this.email.split('@')[1];
        }
    }
})

 

 

methods

methods.html

    <div id="app">
        <p>{{ localEmail }}</p>
    </div>

 

js/methods.js

let app = new Vue({
    el: '#app',
    data: {
        email: 'YUU3@example.net'
    },
    methods: {
        localEmail: function() {
            return this.email.split('@')[0].toLowerCase() + '@' +this.email.split('@')[1];
        }
    }
})

 

v-on

 

on.html

    <div id="app">
        <button v-on:click="onclick">押して!</button>
        <p>{{ now }}</p>
    </div>

 

js/on.js

let app = new Vue({
    el: '#app',
    data: {
        now: '',
    },
    methods: {
        onclick: function() {
            this.now = new Date().toLocaleString();
        }
    }
})

 

v-if

 

vif.html

    <div id="app">
        <p>{{ message }}</p>
        <p v-if="toggle">
            <a v-bind:href="url">優技録</a>
        </p>
    </div>

 

js/vif.js

let app = new Vue({
    el: '#app',
    data: {
        message: 'こんにちわん!',
        url: 'https://www.yuulinux.tokyo/',
        toggle: true
    }
})

 

 

v-for

vfor.html

    <div id="app">
        <p>{{ message }}</p>
        <p v-if="toggle">
            <a v-bind:href="url">優技録</a>
        </p>
        <ul>
            <li v-for="language in languages">{{ language }}</li>
        </ul>
    </div>

 

js/vfor.js

let app = new Vue({
    el: '#app',
    data: {
        message: 'こんにちわん!',
        url: 'https://www.yuulinux.tokyo/',
        toggle: true,
        languages: [
            'JavaScript',
            'PHP',
            'Python'
        ]
    }
})

 

 

 

component

 

component.html

    <div id="app">
        <hello-component></hello-component>
    </div>

 

js/component.js

Vue.component('hello-component', {
    template: '<p>こんにちゃ!</p>'
})

let app = new Vue({
    el: '#app'
})

 

computedとmethodsの違い

 

  • computed
    ・getter, setter
    ・キャッシュされる
  • methods
    ・getter
    ・キャッシュされない

 

computed2.html

<div id="app">
    <p>
        base price: <input type="text" v-model="basePrice">
    </p>
    <p>
        tax included price: <input type="text" v-model="taxIncludedPrice">
    </p>
</div>

 

 

js/computed2.js

let app = new Vue({
    el: '#app',
    data: {
        basePrice: 100
    },
    computed: {
        taxIncludedPrice: {
            get: function() {
                return parseInt(this.basePrice * 1.08); // 整数値を返す
            },
            set: function(taxIncludedPrice) {
                this.basePrice = Math.ceil(taxIncludedPrice / 1.08); // 小数点以下を切り上げてからbasePriceプロパティに代入
            }
        }
    }
})

 

watch

watch.html

<div id="app">
    <p>
        {{ message }}
    </p>
    <p>
        <input type="text" v-model:value="message">
    </p>
    <pre>{{ $data }}<pre>
</div>

 

js/watch.js

let app = new Vue({
    el: '#app',
    data: {
        message: '優技録'
    },
    watch: {
        message: function(newValue, oldValue) {
            console.log('new: %s, old: %s', newValue, oldValue)
        }
    }
})

 

lodashライブラリ

  • _.debounce(関数名, ミリ秒)
    画面同期やサーバ問い合わせでミリ秒待ってから、関数名を実行する

 

クラスのデータバインディング

 

classbind.html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>Vue.js</title>

<style>
.large {
    font-size: 36px;
}

.text-danger {
    color: red;
}

</style>
</head>
<body>
<div id="app">
    <p>
        Hello <span v-bind:class="{large: isLarge, 'text-danger': hasError}">優技録</span>
    </p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="js/classbind.js"></script>
</body>
</html>

 

js/classbind.js

let app = new Vue({
    el: '#app',
    data: {
        isLarge: true,
        hasError: true
    }
})

 

セレクトボックス

 

 

単体選択

select-single.html

<div id="app">
    <select v-model="selected">
        <option disable value="">選択してちょ</option>
        <option>りんご</option>
        <option>ばなな</option>
        <option>しゅーまい</option>
    </select>
    {{ selected }}
</div>

 

select-single.js

let app = new Vue({
    el: '#app',
    data: {
        selected: ''
    }
})

 

複数選択

select-multiple.html

<div id="app">
    <select v-model="selected" multiple>
        <option disable value="">選択してちょ</option>
        <option>りんご</option>
        <option>ばなな</option>
        <option>しゅーまい</option>
    </select>
    {{ selected }}
</div>

 

select-multiple.js

let app = new Vue({
    el: '#app',
    data: {
        selected: []
    }
})

 

 

簡単なアプリをつくろう

 

todolist

 

todolist.html

<!DOCTYPE html>
<html lang="ja">
<head>

<style>
#app ul {
    list-style: none;
}

#app li > span.done {
    text-decoration: line-through;
}
</style>

<meta charset="UTF-8" />
<title>Vue.js</title>
</head>
<body>
    <h2>ToDo list</h2>
    <div id="app">
        <form v-on:submit.prevent>
            <input type="text" v-model="newItem">
            <button v-on:click="addItem">
                追加だ!
            </button>
        </form>
        <ul>
            <li v-for="(todo, index) in todos">
                <input type="checkbox" v-model="todo.isDone">
                <span v-bind:class="{ done: todo.isDone }">{{ todo.item }}</span>
                <button v-on:click="deleteItem(index)">削除</button>
            </li>
        </ul>
        <pre>{{ $data }}</pre>
    </div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="js/todolist.js"></script>
</body>
</html>

 

 

js/todolist.js

let app = new Vue({
    el: '#app',
    data: {
        newItem: '',
        todos: []
    },
    methods: {
        addItem: function(event) {
            // 入力が空の場合はアーリーリターン
            if (this.newItem == '') {
                return;
            }

            var todo = {
                item: this.newItem,
                isDone: false
            };
            this.todos.push(todo); // タスク追加
            this.newItem = '';     // クリア
        },
        deleteItem: function(index) {
            this.todos.splice(index, 1); // splice(削除を開始する配列のインデックス, 削除する個数)
        }
    }
})

 

 

bitcoin

 

bitcoin.html

<!DOCTYPE html>
<html lang="ja">
<head>

<style>
#app ul {
    list-style: none;
}

#app li > span.done {
    text-decoration: line-through;
}

[v-cloak] {
    display: none;
}
</style>

<meta charset="UTF-8" />
<title>Vue.js</title>
</head>
<body>
    <h2>BitCoin App</h2>
    <div id="app">
        <section v-if="hasError">Errorが起きたよ</section>
        <section v-else>
            <div v-if="loading">
                Now Loading...
            </div>
            <ul v-cloak>
                <li v-for="(rate, currency) in bpi">
                    {{ currency }} : {{ rate.rate_float | currencyDecimal }}
                </li>
            </ul>
        </section>
    </div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js"></script> <!-- ●←Axiosを読み込み -->
<script src="js/bitcoin.js"></script>
</body>
</html>

 

 

js/bitcoin.js

let app = new Vue({
    el: '#app',
    data: {
        bpi: null,
        hasError: false,
        loading: true
    },
    mounted: function() {
        axios.get('https://api.coindesk.com/v1/bpi/currentprice.json')
            .then(function(response) {
                // console.log(response);
                // console.log(response.data.bpi);
                //console.log(response.data.bpi.EUR.rate_float);
                this.bpi = response.data.bpi;
            }.bind(this)) // このクラスにバインド。bindで指定しないとthen()の中のthisがWindowオブジェクトを意味してしまう
            .catch(function(error) {
                console.log(error);
                this.hasError = true;
            }.bind(this))
            .finally(function() { // 通信が全て終わった時に、loadingをfalseにする
                this.loading = false;
            }.bind(this))
    },
    filters: {
        currencyDecimal(value) {
            return value.toFixed(2);
        }
    }
})

 

Qiita App

 

index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Real time search</title>
  </head>
  <body>
    <div id="app">
      <p>
          <input type="text" v-model="keyword">
      </p>
      <p>
          {{ message }}
      </p>
      <ul>
          <li v-for="item in items">
            <a v-bind:href="item.url">{{ item.title }}</a> Likes: {{ item.likes_count }}
          </li>
      </ul>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
    <script src="js/main.js"></script>
  </body>
</html>

 

 

js/main.js

var app = new Vue({
    el: '#app',
    data: {
        items: null,
        keyword: '',
        message: ''
    },
    watch: {
        keyword: function(newKeyword, oldKeyword) {
            // console.log(newKeyword);
            this.message = '入力が終わるのを待っています...';
            this.debouncedGetAnswer();
        }
    },
    created: function() {
        this.keyword = 'JavaScript';
        this.getAnswer();
        this.debouncedGetAnswer = _.debounce(this.getAnswer, 1000)
    },
    methods: {
        getAnswer: function() {
            if(this.keyword === '') {
                this.items = null;
                this.message = '';
                return;
            }

            this.message = 'Loading...';
            var vm = this;
            var params = { page: 1, per_page: 20, query: this.keyword }
            axios.get('https://qiita.com/api/v2/items', { params} )
                .then(function(response) {
                    vm.items = response.data;
                    console.log(response);
                })
                .catch(function(error) {
                    vm.message = 'Error! + error';
                })
                .finally(function() {
                    vm.message = '';
                })
        }
    }
})

 

 

Vue-Cli

 

インストール

$ npm install -g @vue/cli

 

プロジェクト作成

$ vue create my-cli
$ cd my-cli

 

ライブラリのインストール

$ vue add element
$ vue add router
$ vue add vuex

 

$ npm install -g @vue/cli-service-global

 

サーバ立ち上げ

$ npm run serve


 DONE  Compiled successfully in 12040ms                                                                           22:47:27

  App running at:
  - Local:   http://localhost:8080/
  - Network: http://192.168.11.2:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

 

http://localhost:8080/

 

Vuex

Vuex 公式のサンプルアプリ

https://jsfiddle.net/n9jmu5v7/1269/

 

html

<div id="app">
  <p>{{ count }}</p>
  <p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </p>
</div>

 

js

// make sure to call Vue.use(Vuex) if using a module system

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
  	increment: state => state.count++,
    decrement: state => state.count--
  }
})

new Vue({
  el: '#app',
  computed: {
    count () {
	    return store.state.count
    }
  },
  methods: {
    increment () {
      store.commit('increment')
    },
    decrement () {
    	store.commit('decrement')
    }
  }
})

 

モジュール

https://vuex.vuejs.org/ja/guide/modules.html

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> `moduleA` のステート
store.state.b // -> `moduleB` のステート

 

 

Udemyの講座やる

 

$ vue create udemy-vuejs
$ npm run build
$ npm run serve

 

main.js

import Vue from 'vue';
import App from './App.vue';

Vue.config.productionTip = false

console.log(App);

new Vue({
  render: h => h(App),
}).$mount('#app');

 

 

Appオブジェクトが確認できた。

 

コンポーネント props, $emit

main.js

import Vue from 'vue';
import App from './App.vue';

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app');

 

App.vue

<template>
  <div>
    <LikeHeader :total-number="number"></LikeHeader>
    <LikeNumber :total-number="number" @my-click="incrementNumber"></LikeNumber>
    <LikeNumber :total-number="number"></LikeNumber>
  </div>
</template>>

<script>
import LikeHeader from './components/LikeHeader.vue';
import LikeNumber from './components/LikeNumber.vue';

export default {
    components: {
        LikeHeader,
        LikeNumber
    },
    data() {
      return {
        number: 10
      }
    },
    methods: {
      incrementNumber(value) {
        this.number = value;
      }
    }
}
</script>

 

components/LikeHeader.vue

<template>
  <div>
    <h2>いいね{{ number() }}</h2>
  </div>
</template>

<script>
export default {
  props: ["totalNumber"],
  methods: {
    number() {
      return this.totalNumber;
    }
  }
}

</script>>

<style scoped>
  div {
    border: 1px solid blue;
  }
</style>>

 

components/LikeNumber.vue

<template>
  <div>
    <p>いいね{{ halfNumber }}
      <button @click="increment">+1</button>
    </p>
  </div>
</template>

<script>


export default {
    props: {
      totalNumber: {
        type: Number
      }
    },
    computed: {
      halfNumber() {
        return this.totalNumber / 2;
      }
    },
    methods:{
      increment() {
          //this.totalNumber += 1;
          this.$emit("my-click", this.totalNumber + 1)
      }
    }
}
</script>

<style scoped>
  div {
    border: 1px solid red;
  }
</style>>

 

 

 

 

 

Amazonおすすめ

iPad 9世代 2021年最新作

iPad 9世代出たから買い替え。安いぞ!🐱 初めてならiPad。Kindleを外で見るならiPad mini。ほとんどの人には通常のiPadをおすすめします><

コメントを残す

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

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)