$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
name: (vue_hands_on)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC) MIT
About to write to /Users/shinpei/nekogata/vue_hands_on/package.json:
{
"name": "vue_hands_on",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT"
}
Is this ok? (yes) yes
Last active
December 3, 2018 05:52
-
-
Save Shinpeim/7dc6850e2fb3cb2d39ac2b5a985d86e7 to your computer and use it in GitHub Desktop.
Vue.js 入門
$ npm install --save-dev webpack babel-core babel-loader babel-preset-es2015 babel-plugin-add-module-exports babel-preset-stage-0
$ npm install --save babel-polyfill
バベル設定するでヤンス
$ vim .babelrc
$ cat .babelrc
{
"presets": [
"es2015",
"stage-0"
],
"plugins": [
"add-module-exports"
]
}
webpack設定するでヤンス
$ vim webpack.config.js
$ cat webpack.config.js
const path = require('path');
const config = {
entry: ['./src/js/main.js'],
output: {
path: __dirname + "/build/js",
filename: 'main.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel', // 'babel-loader' is also a legal name to reference
query: {
presets: ['es2015']
}
},
]
},
resolve: {
modulesDirectories: [
path.resolve("src/js"),
path.resolve("node_modules"),
path.resolve("web_modules")
]
},
plugins: []
};
module.exports = config;
ディレクトリ作っとくでヤンス
$ mkdir -p src/js
$ mkdir -p build/js
npm scriptでビルドできるようにしとくでヤンス
$ vim package.json
$ cat package.json
{
"name": "vue_hands_on",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --progress",
"watch": "webpack -d --watch --progress"
},
"author": "",
"license": "MIT",
"devDependencies": {
"babel-core": "^6.11.4",
"babel-loader": "^6.2.4",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-preset-es2015": "^6.9.0",
"babel-preset-stage-0": "^6.5.0",
"webpack": "^1.13.1"
},
"dependencies": {
"babel-polyfill": "^6.9.1"
}
}
$ npm install vue --save
- build/index.html
<html>
<head>
</head>
<body>
<div id="main">{{message}}</div>
<script src="./js/main.js"></script>
</body>
</html>
- src/js/main.js
import Vue from "Vue"
new Vue({
el: '#main',
data: {
message: 'Hello, world!'
}
});
$ npm run build
- VueクラスのインスタンスがViewModel(Controllerの役割をするやつ)になる。
- ViewModelはひとつのDOM要素と1:1でbindされる
- コンストラクタに渡すoptionのdataプロパティが「データバインド」される
- データバインドされた値はテンプレートからは{{variableName}}で参照できる
- index.html
<html>
<head>
</head>
<body>
<div id="main">
{{message}}
<input type="button" value="change the world" v-on:click="changeTheWorld">
</div>
<script src="./js/main.js"></script>
</body>
</html>
- main.js
import Vue from "Vue"
new Vue({
el: '#main',
data: {
message: 'Hello, world!'
},
methods: {
changeTheWorld: function(){
console.log(this);
this.message = 'Hello, changed world!';
}
}
});
- v-onを使うことでVMのメソッドを叩ける
- methods オプションで定義する
- 定義したmethod内のthisはVMを指す。
- dataで生やしたものはVMのインスタンスも持ってる
- それを書き換えると「データバインド」されてる側も勝手に書きかわる
- index.html
<html>
<head>
</head>
<body>
<div id="main">
<p>{{message}}</p>
<input type="input" v-model="message">
<input type="button" v-on:click="resetMessage" value="reset">
</div>
<script src="./js/main.js"></script>
</body>
</html>
- main.js
import Vue from "Vue"
const initialMessage = 'Hello, world!';
new Vue({
el: '#main',
data: {
message: initialMessage
},
methods: {
resetMessage: function(){
this.message = initialMessage
}
},
});
- 双方向binding
- input系のタグにv-modelを指定すると、ブラウザ上でその内容を書き換えるとdataの内容も書きかわる。
- dataの内容をJavaScriptで書き換えると、input系タグの内容も書きかわる。
どういうhookがあるかはAPI reference読んでおくと良い
import Vue from "Vue"
const initialMessage = 'Hello, world!';
new Vue({
el: '#main',
created: function(){
this.message = "hello, world";
},
data: {
message: ""
},
methods: {
resetMessage: function(){
this.message = initialMessage
}
},
});
-
連打用ボタンが置いてある
-
連打された数がわかるカウンタが置いてある
-
ネットワーク越しにみんなで連打できる
-
クリックされるたびにHTTPリクエストを飛ばされたら目も当てられない通信量になる
-
だれかがクリックするたびにサーバーからpushされてきたら目も当てられない通信量になる
-
クライアント側:一定時間クリック数をバッファして定期的にサーバーに送りつける
-
サーバー側:一定時間おきにクライアントに対してpushする
class Counter {
constructor(){
this.count = 0;
}
increment(){
this.count = this.count + 1;
}
}
class Buffer {
constructor(){
this._count = 0;
}
increment(){
this._count++;
}
flush(){
//本来はちゃんとサーバーにpostする
console.log("flush buffer! count:" + this._count);
this._count = 0;
}
}
class Listener {
constructor(counter){
this._counter = counter;
}
start(){
//本来はちゃんとサーバーに接続してpushを待つ
let c = 10;
setInterval(()=>{
this._counter.count = c;
c += 10;
}, 2 * 1000);
}
}
class ClickCounterApplicationService {
/**
* @param counter {Counter}
* @param buffer {Buffer}
* @param listener {Listener}
*/
constructor(counter, buffer, listener){
this.counter = counter;
this._buffer = buffer;
this._listener = listener;
}
start(){
this._listener.start();
}
flush(){
this._buffer.flush();
}
click(){
this.counter.increment();
this._buffer.increment();
}
}
import Vue from "Vue";
new Vue({
el: '#main',
created: function(){
const counter = new Counter;
const buffer = new Buffer();
const listener = new Listener(counter);
this.applicationService = new ClickCounterApplicationService(counter, buffer, listener);
this.applicationService.start();
setInterval(() => {
this.applicationService.flush();
}, 5 * 1000);
},
data: {
count: 0
},
methods: {
click: function () {
this.applicationService.click();
}
}
});
<html>
<head>
</head>
<body>
<div id="main">
<h1>{{count}}</h1>
<input type="button" v-on:click="click" value="CLICK ME!">
</div>
<script src="./js/main.js"></script>
</body>
</html>
- VMがCounterモデルの変更を監視してUIに反映するようにする
// Counterモデルをobservableにする
class Counter {
set count(c){
this._count = c;
this._notify();
}
get count(){
return this._count;
}
constructor(){
this._observers = [];
this.count = 0;
}
increment(){
this.count = this.count + 1;
}
observe(f){
this._observers.push(f);
}
_notify(){
for (let i = 0; i < this._observers.length; i++) {
this._observers[i](this.count);
}
}
}
import Vue from "Vue";
new Vue({
el: '#main',
created: function(){
const counter = new Counter;
const buffer = new Buffer();
const listener = new Listener(counter);
this.applicationService = new ClickCounterApplicationService(counter, buffer, listener);
// ここ追加
this.applicationService.counter.observe((c) => {
this.count = c;
});
this.applicationService.start();
setInterval(() => {
this.applicationService.flush();
}, 5 * 1000);
},
data: {
count: 0
},
methods: {
click: function () {
this.applicationService.click();
}
}
});
new Vue({
el: '#main',
created: function(){
const counter = new Counter;
const buffer = new Buffer();
const listener = new Listener(counter);
this.applicationService = new ClickCounterApplicationService(counter, buffer, listener);
// アニメーションするように変更
this.applicationService.counter.observe((c) => {
const i = setInterval(() => {
if (this.count >= c) {
clearInterval(i);
} else {
this.count += 1;
}
}, 10);
});
this.applicationService.start();
setInterval(() => {
this.applicationService.flush();
}, 5 * 1000);
},
data: {
count: 0
},
methods: {
click: function () {
this.applicationService.click();
}
}
});
- データバインドの細かい機能(filterとかそういうやつ)
- Computed Properties
- Class and Style Bindings
- v-ifとかの条件つきレンダリング
- v-forなどのリストレンダリング
- ラジオボタンとかへのbinding
- 再描画時アニメーション
- コンポーネント
- Mixin
- vueify,vue-loader
- vue-router
日本語もあるけど訳が微妙なところ結構あるので結局英語で読んだほうがいいです
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment