vuexのソースを見てて理解できないとこ。その1
src/util.js
/**
* Deep clone an object. Faster than JSON.parse(JSON.stringify()).
*
* @param {*} obj
* @return {*}
*/
export function deepClone (obj) {
if (Array.isArray(obj)) {
return obj.map(deepClone)
} else if (obj && typeof obj === 'object') {
var cloned = {}
var keys = Object.keys(obj)
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i]
cloned[key] = deepClone(obj[key])
}
return cloned
} else {
return obj
}
}
for文の中にある「l」はなんの意味があるんやろうか?
for (var i = 0; i < keys.length; i++) {
じゃあだめなんやろか?
パフォーマンスの問題かと思って50万回ぐらい実行したタイムを比較したら特に違いが見られなかったんだよねぇー
んで、書式的にもlが理解できない。
var でもない。let をつけたらコンパイルエラー。
何これ?
vuejsプロジェクト雛形を楽に作りたい
2日経つと前に何作ってたか忘れてまた最初からやりたくなる病。
そのために作り始めを早めるメモ
主に組み込むものとバージョン
- node(v5.4.0)
- npm(3.5.3)
- vue(^1.0.14)
- vuex(^0.2.0)
- es6
- mocha(2.3.4)
- power-assert(1.2.0)
手順概要
- ディレクトリ用意
- いろいろインストール
- 環境に必要なもの用意
- 小さいvuexサンプル
- 最小テスト
手順詳細
ディレクトリ用意
# ディレクトリ作成
mkdir プロジェクトのフォルダ
cd プロジェクトのフォルダ
mkdir -p {build,test/{unit,e2e},src/{components,views/app,filters,directives,assets/{js,style,images}}}
いろいろインストール
npm init --y
npm i -g webpack webpack-dev-server mocha babel-core babel-loader power-assert
npm i -S vue vuex
npm i -D babel-core babel-loader webpack style-loader css-loader sass-loader html-loader mocha mocha-loader babel-plugin-add-module-exports babel-plugin-transform-runtime babel-polyfill babel-preset-es2015 babel-preset-stage-2 babel-runtime file-loader url-loader espower-babel power-assert
環境に必要なもの用意
.babelrc
{
"presets": ["es2015", "stage-2"]
}
webpack.config.js
module.exports = {
entry: {
app: "./src/assets/js/app.js"
},
output: {
path: './build/js',
publicPath: '/js/',
filename: "[name].js"
},
resolve: {
alias: {
vue: "vue/dist/vue"
},
modulesDirectories: ['node_modules', 'src/', 'src/assets/js/**', 'src/assets/style/**', 'src/views/**', 'src/directives/**', 'src/filters/**', 'src/components/**'],
// require()するときに拡張子を省略可能にします
extensions: ['', '.webpack.js', '.web.js', '.js']
},
devServer: {
contentBase: "./build",
},
module: {
preloaders: [],
loaders: [
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "url-loader?limit=10000&minetype=application/font-woff"
},
{
test: /\.png$/,
loader: "url-loader?limit=100000"
},
{
test: /\.jpg$/,
loader: "file-loader"
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "file-loader"
},
{
test: /\.scss$/,
loader: "style!css!sass"
},
{
test: /\.html$/,
loader: "html"
},
{
test: /\.js(x?)$/,
loader: 'babel-loader?sourceMaps=true'
}
]
}
};
package.jsonのscriptsの中身を書き換え
"scripts": {
"hot": "webpack-dev-server -d --inline",
"test": "mocha --compilers js:espower-babel/guess test/unit",
"e2e": "mocha --compilers js:espower-babel/guess test/e2e"
},
上から、
npm run hot
でデバッグ用のサーバ起動するためのもの
npm test
でtest/unit配下に格納したテストを実行するもの
npm run e2e
でe2eテストに格納したテストが動くはず(今回はやらない)
小さいvuexサンプル
前段その1サーバ起動確認
build/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>sample</title>
</head>
<body>
<div id="app">this is app</div>
<script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>
src/assets/js/app.js
console.log('hoge');
ここでコンソール上でnpm run hot
を実行して下記URLで"this is app"、デバッグコンソールに"hoge"と表示されればここまでOK
前段その2小さいvueコンポーネント
build/index.html書き換え
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>sample</title>
</head>
<body>
<app></app>
<script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>
src/assets/js/app.js書き換え
import Vue from 'vue'
import App from '../../views/app'
new Vue({
el: 'body',
components: { App }
});
src/views/app/index.js
export default {
template: require('./template.html')
}
src/views/app/template.html
<div>this is app view</div>
http://localhost:8080/
にthis is app viewと表示されていればOK
小さいvuexサンプル(vuexさん公式のcounterサンプルを丸パクリします)
src/views/app/index.js書き換え
import Counter from '../../components/counter'
export default {
template: require('./template.html'),
components: {
"counter": Counter
}
}
src/views/app/template.html書き換え
<counter></counter>
src/components/counter/index.js
import store from '../../assets/js/store'
export default {
template: require('./template.html'),
computed: {
count () {
return store.state.count
}
},
methods: store.actions
}
src/components/counter/template.html
<div>
Clicked: {{ count }} times
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementIfOdd">Increment if odd</button>
<button @click="incrementAsync">Increment async</button>
</div>
src/assets/js/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
// mutation types
// optional if you don't like constants.
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
// root state object.
// each Vuex instance is just a single state tree.
const state = {
count: 0
};
// actions are what components will be able to
// call as store.actions.xxx
// note these are not the final functions the
// components will be calling.
const actions = {
// for simple actions that just dispatches a single mutation,
// we can just provide the mutation type.
increment: INCREMENT,
decrement: DECREMENT,
// for a normal action function, it always recieves the store
// instance as the first argument, from which we can get the
// dispatch function and the state object. Any additional
// arguments will follow the store argument.
incrementIfOdd: ({ dispatch, state }) => {
if ((state.count + 1) % 2 === 0) {
dispatch(INCREMENT)
}
},
// Same thing for async actions.
incrementAsync: ({ dispatch }) => {
setTimeout(() => {
dispatch(INCREMENT)
}, 1000)
}
};
// mutations are operations that actually mutates the state.
// each mutation handler gets the entire state tree as the
// first argument, followed by additional payload arguments.
// mutations must be synchronous and can be recorded by middlewares
// for debugging purposes.
const mutations = {
[INCREMENT] (state) {
state.count++
},
[DECREMENT] (state) {
state.count--
}
};
// A Vuex instance is created by combining the state, the actions,
// and the mutations. Because the actions and mutations are just
// functions that do not depend on the instance itself, they can
// be easily tested or even hot-reloaded (see counter-hot example).
//
// You can also provide middlewares, which is just an array of
// objects containing some hooks to be called at initialization
// and after each mutation.
export default new Vuex.Store({
state,
actions,
mutations
})
http://localhost:8080/
にカウンターが表示されていればOK
最小テスト
test/unit/store-test.js
import assert from 'power-assert';
import store from '../../src/assets/js/store'
describe('storeのテスト', () => {
it('mutationsのincrement処理を実行するとstateのcountが増える', () => {
let before = store.state.count;
store.actions.increment();
let after = store.state.count;
assert(before < after);
});
it('mutationsのdecrement処理を実行するとstateのcountが減る', () => {
let before = store.state.count;
store.actions.decrement();
let after = store.state.count;
assert(before > after);
});
});
npm test
で実行して結果が表示されればOK
assert(before === after)
などに書き換えてエラーを出してみるのもよいかも
es6のファイル名問題。
Nightmareさんとこをざっくり訳
英語わかんねっす。
Nightmare
Nightmareはハイレベルな自動ページ表示ライブラリーです。
達成したいことは、ネストが深く分かり難いコールバック地獄なしに下のことを実現する
- シンプルに書ける
- 同期処理っぽく書ける
これは、APIを持っていないサイトのE2Eテスト用に設計されています。
Electronベースでできてます。PhantomJSに似てますが、もっと早くてモダンです。
Daydream
Daydreamは@stevenmiller888さんによって作られた、Nightmareを使う際のお助けツール
chromeのエクステンションで、ブラウザ操作でNightmare用スクリプトを生成するものです。
Examples
yahooをサーチしてみよう
var Nightmare = require('nightmare');
var vo = require('vo');
vo(function* () {
var nightmare = Nightmare({ show: true });
var link = yield nightmare
.goto('http://yahoo.com')
.type('input[title="Search"]', 'github nightmare')
.click('.searchsubmit')
.wait('.ac-21th')
.evaluate(function () {
return document.getElementsByClassName('ac-21th')[0].href;
});
yield nightmare.end();
return link;
})(function (err, result) {
if (err) return console.log(err);
console.log(result);
});
以下のコマンドで実行できます
npm install nightmare vo
node --harmony yahoo.js
もしくは mochaのテストを実行してみましょう:
var Nightmare = require('nightmare');
var expect = require('chai').expect; // jshint ignore:line
describe('test yahoo search results', function() {
it('should find the nightmare github link first', function*() {
var nightmare = Nightmare()
var link = yield nightmare
.goto('http://yahoo.com')
.type('input[title="Search"]', 'github nightmare')
.click('.searchsubmit')
.wait('.ac-21th')
.evaluate(function () {
return document.getElementsByClassName('ac-21th')[0].href;
});
expect(link).to.equal('https://github.com/segmentio/nightmare');
});
});
全機能の例はこっち
https://github.com/segmentio/nightmare/blob/master/test/index.js
※この例はmocha-generatorsを使ってるから注意してね
動かすには
npm install
npm test
API
Nightmare(options)
Web参照できる新しいインスタンスを生成します。
指定できるオプションはこれ
https://github.com/atom/electron/blob/master/docs/api/browser-window.md#new-browserwindowoptions
加えてnightmareのオプションとして
waitTimeout
.wait()
が指定の時間までにtrueを返さないとexceptionを投げます。
paths
Electronが使用するデフォルトシステムパス。
下のようにして上書き可能
var nightmare = Nightmare({
paths: {
userData: '/user/data'
}
});
switches
Chromeで使えるコマンドラインスイッチ
Electronでサポートしているのは下の通り
https://github.com/atom/electron/blob/master/docs/api/chrome-command-line-switches.md
electronPath
Electronのバイナリを指定。別バージョンのElectronでテストしたいときに使う。
.useragent(useragent)
Electronで使われるuseragentを指定する
.end()
キューを完了し、Electronのプロセスを切断、終了します。
ページ操作
.goto(url
指定したURLのページをロードします。
.back()
バックします。
.forward()
進みます
.refresh()
ページをリフレッシュします。
.click(selector)
指定したセレクタでクリックイベントを発生させます。
.mousedown(selector)
指定したセレクタでマウスダウンイベントを発生させます。
.type(selector[, text])
指定したセレクタに文字入力する。空文字やfalseを設定すると対象のセレクタの値がクリアされる
.check(selector)
.select(selector, option)
指定したdropdownセレクタのオプションを変える
.scrollTo(top, left)
スクロールする
.inject(type, file)
指定したフィアルをページにロードする。ロードできるのはjsかcss
.evaluate(fn[, arg1, arg2,...])
指定したfnを指定した引数で実行する。引数はオプショナル。実行終了後にfnの戻り値が戻り値となる。
情報を抜き取るときに便利
var selector = 'h1';
var text = yield nightmare
.evaluate(function (selector) {
// now we're executing inside the browser scope.
return document.querySelector(selector).innerText;
}, selector); // <-- that's how you pass parameters from Node scope to browser scope
.wait(ms)
指定したミリ秒待つ
.wait(selector)
指定したセレクタが存在するまで待つ(.wait('#pay-button'
)
.wait(fn[, arg1, arg2,...])
指定したfnがtrueを返すまで待つ
ページから情報を抜き取る
.exists(selector)
指定したselectorが存在するかどうか
.visible(selector)
指定したselectorが表示状態か非表示状態か
.on(event, callback)
ページのイベントを関ししてコールバックを呼ぶ。
.goto()
を呼ぶ前に読んでおかないといけない
サポートしているイベントはここ
http://electron.atom.io/docs/v0.30.0/api/browser-window/#class-webcontents
追加されているページイベント
.on('page', function(type="error", message, stack))
このイベントはページで何かしらjavascriptのエラーが起きたときに発火します。
しかし、挿入されたjavascriptコードでは発火しません。(例 .evaluate()
)そういうときはただの例外
ページのイベント
window.addEventListener('error')
, alert(...)
,prompt(...)
とかconfirm(...)
を監視します
.on('page', function(type="alert", message))
Nightmareではデフォルトでポップアップのwindow.alert
が無効です。
しかし監視できます。
.on('page', function(type="prompt", message, response))
Nightmareではデフォルトでポップアップのwindow.prompt
が無効です。
しかし監視できます。
もし、異なるものをハンドリングしたい場合は独自のプリロードスクリプトを用意する必要があります。???なんのこっちゃ
.on('page', function(type="confirm", message, response))
Nightmareではデフォルトでポップアップのwindow.prompt
が無効です。
しかし監視できます。
もし、異なるものをハンドリングしたい場合は独自のプリロードスクリプトを用意する必要があります。???なんのこっちゃ
.on('console', function(type [, arguments, ...]))
type
にはlog
,warn
もしくはerror
、そしてargumants
はコンソールから渡されてくるものです。
.on('console', function(type, errorMessage, errorStack))
このイベントはconsole.logがページ内で使われているときに発火します。しかし、injectされたscriptでは発火しません(例 console.log()の中で.evalute()
)
.screenshot([path][, clip])
現在ページのスクリーンショットを取ります。デバッグに便利。
出力はpngです。引数はどっちともオプショナルです。
pathが指定された場合、画像を指定のディレクトリに保存します。指定されてないと画像データのバッファを返します。
clipが指定された場合、下にもあるようにイメージが矩形にクリップされます。
https://github.com/atom/electron/blob/master/docs/api/browser-window.md#wincapturepagerect-callback
.pdf(path, options)
指定されたパスにpdfファイルを保存します。細かいオプションについての情報は下
https://github.com/atom/electron/blob/v0.35.2/docs/api/web-contents.md#webcontentsprinttopdfoptions-callback
.title()
現在ページのタイトルを返却します。
.url()
現在ページのurlを返却します。
クッキー
.cookies.get(name)
指定した名前のクッキーを取得します。対象のurlは現在ページのurlです。
.cookies.get(query)
クエリを使って複数のクッキーを取得します。もしquery.name
が指定された場合、最初に見つかった値、もしくは配列を返します。
query.url
が指定されていない場合は現在urlになります
例)
// get all google cookies that are secure
// and have the path `/query`
var cookies = yield nightmare
.goto('http://google.com')
.cookies.get({
path: '/query',
secure: true
})
使えるプロパティは下
https://github.com/atom/electron/blob/master/docs/api/session.md#sescookiesgetdetails-callback
.cookies.get()
現在ページのurlをすべて取得します。
.cookies.set(name, value)
現在ページのクッキーをセットします。
.cookies.set(cookie)
クッキーをセットします。もしcookie.urlが指定されてない場合、現在ページにセットします。
例)
yield nightmare
.goto('http://google.com')
.cookies.set({
name: 'token',
value: 'some token',
path: '/query',
secure: true
})
使えるプロパティ一覧は下
https://github.com/atom/electron/blob/master/docs/api/session.md#sescookiessetdetails-callback
.cookies.set(cookies)
一度に複数のcookieをセットします。cookies
はcookie
の配列です。
詳しくは.cookies.set(cookie)
で
Nightmareの拡張
Nightmare.action(name, action|namespace)
下の例のようにカスタムアクションをNightmareのプロトタイプに追加できます。
例)
Nightmare.action('size', function (done) {
this.evaluate_now(function() {
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
return {
height: h,
width: w
}
}, done)
})
var size = yield Nightmare()
.goto('http://cnn.com')
.size()
注意:これはstatic classに追加してます。Nightmareのインスタンスに追加してるわけじゃないです。
evaluate_now
という処理を読んでいます。これはnightmare.evaluate
とは違います。
これは即時に実行されますが、nightmare.evaluate
はキューにたまります。
忘れないための簡単な方法は:evaluateについて疑問におもったとき、もしカスタムアクションを作ってるときならevaluate_nowを使ってください
なぜならすでにキューイングされたものを処理している最中に、その処理をまたキューにためてはいけないからです
またカスタムのネームスペースを作ることもできます。
nightmare.cookies.get
,nightmare.cookies.set
などで内部でも使っているように
アクションをまとめるのに便利です。しかしnightmareオブジェクトが乱雑になります。
例)
Nightmare.action('style', {
background: function (done) {
this.evaluate_now(function () {
return window.getComputedStyle(document.body, null).backgroundColor
}, done)
}
})
var background = yield Nightmare()
.goto('http://google.com')
.style.background()
.use(plugin)
nightmare.use
は一つのインスタンスでタスクを再利用するのに便利です。
nightmare-swiftlyでサンプルをチェックしてください
https://github.com/segmentio/nightmare-swiftly
Custom preload script
ウィンドウ環境起動時になにかしたいときは、プリロードスクリプトを定義できます。
どうやるかっていうと
var nightmare = Nightmare({
webPreferences: {
preload: custom-script.js
}
})
このプリロードするスクリプトは下の記述を入れておく
window.__nightmare = {};
__nightmare.ipc = require('ipc');
使い方
インストール
NightmareはNodeのmoduleなのでNode.jsは入れておく。
インストールはnpm install
で行う
$npm install --save nightmare
実行
Nightmareはnodeのスクリプトやmoduleから利用できる。
例)
var Nightmare = require('../nightmare');
var vo = require('vo');
vo(run)(function(err, result) {
if (err) throw err;
});
function *run() {
var nightmare = Nightmare();
var title = yield nightmare
.goto('http://cnn.com')
.evaluate(function() {
return document.title;
});
console.log(title);
yield nightmare.end();
}
これはcnn.jsとして保存したら下のように実行する
npm install vo nightmare
node --harmony cnn.js
デバッグ
内部で何が起きてるかをしるために3つの方法があります。
1. DEBUG=*
デバッグフラグ
1. Nightmareコンストラクタに{show:true}
を渡すと実際にウィンドウを表示する
1. specific eventsを監視する(下URL参照)
※https://github.com/segmentio/nightmare#onevent-callback
同じテストをデバッグモードで動かすときはDEBUG=nightmare node --harmony cnn.js
windowsなら(set DEBUG=nightmare & node cnn.js
)
そうすると追加情報が出力されます。
テスト
MochaとChaiを使ってテストします。どっちともnpmでインストールします。
nightmareのテストはmake test
で実行します
テストできたら下のように見えます。
make test
․․․․․․․․․․․․․․․․․․
18 passing (1m)
実践Node.jsプログラミングのマルチルームチャットアプリの構築を写経した時のメモ
世界にはまだまだ知らないことだらけ。Node.jsのサーバサイドについても把握せねば。
環境
- node v4.2.3
- mime 1.3.4 (本では1.2.7)
- socket.io 1.3.7 (本では0.9.6)
単純に動かなかった2点
1点目 chat_server.js l50~l60あたり
//var usersInRoom = io.sockets.clients(room);
// ↑だとclientsなんぞ知らん。というエラーが起きる
var usersInRoom = findClientsSocket(room);
// 以下のメソッドを別途追加
function findClientsSocket(roomId, namespace) {
var res = []
, ns = io.of(namespace ||"/"); // the default namespace is "/"
if (ns) {
for (var id in ns.connected) {
if(roomId) {
var index = ns.connected[id].rooms.indexOf(roomId) ;
if(index !== -1) {
res.push(ns.connected[id]);
}
} else {
res.push(ns.connected[id]);
}
}
}
return res;
}
2点目 chat_server.js l20~l30あたり
//socket.emit('rooms', io.sockets.manager.rooms);
// ↑だと「TypeError: Cannot read property 'rooms' of undefined」というエラーが起きる
socket.emit('rooms', io.sockets.rooms);
なぜ動かなかったか?
APIが変わったから。
どうやらsocket.ioの1.0になったときにいろいろ変わったらしいですね
ふぅ。
Server側復習
server.js => ほぼstaticなwebサーバに関する記述
chat_server => socket.ioに関するところだけ抜き出して意味を調べてみる
io = socketio.listen(server)
API docsより
Server#listen
Synonym of Server#attach.
Server#attach(srv:http#Server, opts:Object):Server
Attaches the Server to an engine.io instance on srv with the
supplied opts (optionally).
engine.ioとはなんぞや?
https://github.com/socketio/engine.io
socket.io用のトランスポート層で双方向通信するための実装ということか?
これをhttpサーバにアタッチすることでリクエストをインターセプトする
io.set('log level', 1);
意図がわからない。log levelを1にするということはログを多くすることなのか?少なくすることなのか?ログを無くしたいのか?
そしてversion1.0以降はなにやら変わっているらしい。このログレベルの設定自体が不要なのか?
http://socket.io/docs/logging-and-debugging/
↓で何やら説明があった。
http://socket.io/docs/migrating-from-0-9/
Options like log-level are gone.
ごーん
socket.emit('eventName', obj);
対象のsocketに対してイベントを発火させる。
渡したいものはobjに詰めておく
socket.join(room)
API docsより
Socket#join(name:String[, fn:Function]):Socket
Adds the socket to the room, and fires optionally a callback fn
with err signature (if any).
The socket is automatically a member of a room identified with its
session id (see Socket#id).
The mechanics of joining rooms are handled by the Adapter
that has been configured (see Server#adapter above), defaulting to
socket.io-adapter.
roomに追加してoptionのコールバックを発火。
roomとはなにものか?
デフォルトではセッションID名のroomに自動的に入れられているってことか
socket.leave
joinの反対で良い模様
socket.broadcast.to(room).emit('message', {...})
ブロードキャスト。
そして↓のように書いても動いた。
socket.to(room).emit('message', {...}
違いはなんだろう?
socket.on('イベント名', function(パラメータ){ハンドリング処理});
見ての通りのイベントハンドリング処理の模様
io.of(...)
カスタムのネームスペースを作れるらしい。
デフォルトは"/"
socket.id
API docsより
Socket#id:String
A unique identifier for the socket session, that comes from the
underlying Client.
はい。
Client側復習
io
おもむろに登場するグローバルオブジェクト。
socket.on('イベント名’, function(パラメータ){ハンドリング})
イベントのハンドリング
socket.emit('イベント名', パラメータ)
イベントの発火
クライアントはハンドリングと発火だけなのでシンプル
vuejsの作者さんが考えたvuejsにマッチするflux?
vuexを動かしてみる
動機:githubで見つけて単純にDLして動かそうとしたら動かなかったから
環境メモ
- babelは5系
- nodejsは4.2.2
- npmは3.5
- .vueファイルを使わない(ただの個人的な好み)
作業順
- ディレクトリを作る
- npm でいろいろインストール
- vuexをプロジェクトの中に
- exampleにあるcounterを移植して動かしてみる
- testを移植して動かしてみる
[ディレクトリを作る]
# ディレクトリ作成
mkdir プロジェクトのフォルダ
cd プロジェクトのフォルダ
mkdir -p build test src/{components,views,assets/{js,css}}
[npm でいろいろインストール]
# npm で必要なものをあつめてくる
npm init
npm i -g webpack webpack-dev-server mocha babel-loader@^5.3
npm i -S vue
npm i -D babel-loader@^5.3 webpack style-loader css-loader sass-loader html-loader mocha mocha-loader chai
[vuexをプロジェクトの中に]
今回は/src/assets/vuexというディレクトリを用意してその中にgithubから持ってきたvuexのsrc配下を入れる
[exampleにあるcounterを移植して動かしてみる]
build/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>vuex counter example</title>
</head>
<body>
<counter></counter>
<script src="js/app.js"></script>
</body>
</html>
src/assets/js/main.js(vuexのexampleのままimportのパスを変えただけ)
import Vue from 'vue'
import Counter from '../../components/counter/index'
new Vue({
el: 'body',
components: { Counter }
})
src/assets/js/vuex.js(vuexのexampleのcounter内にあるvuex.jsをそのままもってきてimportのパスだけ変更)
import Vue from 'vue'
import Vuex from '../vuex'
~省略
src/components/counterにCounter.vueを分割して2ファイル
index.js
import vuex from '../../assets/js/vuex'
export default {
template: require('./template.html'),
computed: {
count () {
return vuex.state.count
}
},
methods: vuex.actions
}
template.html
<div>
Clicked: {{ count }} times
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementIfOdd">Increment if odd</button>
<button @click="incrementAsync">Increment async</button>
</div>
サーバを起動して確認
webpack-dev-server -d --inline
[testを移植して動かしてみる]
testディレクトリにあるtest.jsをそのまま移植してimportのパスだけ直す
mocha --compilers js:babel-core/register
通りました。これでいろいろ試せるかな
見ないふりをしてたけど、eslintを入れて動かすとなんか警告が出る。けどなんの警告だかはわかってない
findConfigFileの引数が変わってます。
完全に元のエントリーの内容残って無いけど、うそんこタイトル残しとくよりマシかな!という判断で書き直し
20151124版のtypescript1.8.0-dev.20151124のfindConfigFileメソッドは第2引数にfileのexistsを確認するための関数を渡さなければいけなくなった。
※具体的にいつのリリースでそういう仕様になったかはわからないけれど、つい最近なんだろうなーと想像
そのために、既存のfindConfigFileを利用していたライブラリはそれに対応しないとエラーが発生するようになっている。
2015年11月24日時点でespower-typescript-babelを利用しようとすると当該のエラーにぶつかった。
findConfigFileメソッドを利用している箇所をルートパス+"tsconfig.json"をセットするように変更してしまえば動いた。けど、ちゃんと対応するなら第2引数にisExistsをわたしてあげないとか?
そもそも1.6系使えば動きそうだからわざわざ1.8の安定してないやつ使う必要がなくなったのでは?