- 投稿日:2020-02-05T16:38:01+09:00
vueのstorybookにobjectのpropsを入れるメモ
よく見るやつ
import { storiesOf } from '@storybook/vue' import ItemComponent from './ItemComponent.vue' storiesOf('ItemComponent', module).add('default', () => { const title = 'test' return { components: { ItemComponent }, template: ` <item-component title='${title}' />` } })いや、そうじゃないんだよな…
Objectとか型付けたデータを渡したい……よく見たらこれ、.vueの中身を返してるだけじゃね?
import { storiesOf } from '@storybook/vue' import ItemComponent from './ItemComponent.vue' import Item from '@/types/Item' storiesOf('ItemComponent', module).add('default', () => { const item: Item = { id: 'ddd', title: 'test', body: 'test' } return { components: { ItemComponent }, data: () => { return { item } }, template: ` <item-component :item='item' />` } })こうじゃ!!!!!!!!!
めでたしめでたし。
- 投稿日:2020-02-05T15:44:37+09:00
Vue3.0とReactive Programmingの実践
自己紹介
Mikihiro Saito
フロントエンジニア
2020年3月末からフィリピンで開発業務
Javascript(Typescript)
Vue3.0がもう少しでやってくる!
新しく導入される機能
Composition API
Fragment
Portal
Suspense
リアクティブプログラミングとは
解決するため
複雑な時間の概念
命令の実行順序を管理することができない
幾重にも連なるコールバック
命令の実行順序を管理することができない
コードは読みづらくなる...
解決するために
React hooks
Vue Composition API
Angular RxJS
2つの概念に分けた
時間を処理する「behavior」
値を処理する「event」
今回のトピック
Composition API
https://vue-composition-api-rfc.netlify.com/
Composition APIとは
Vue版のReactのhooks
公式のReact hooks実装例
import React, { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
これをVueで?
これまでのVue記法
<script> export default { name: 'demo', data: { branches: ['master', 'dev'], currentBranch: 'master', commits: null }, created: function () { this.fetchData() }, watch: { currentBranch: 'fetchData' }, filters: { truncate: function (v) { var newline = v.indexOf('\n') return newline > 0 ? v.slice(0, newline) : v }, formatDate: function (v) { return v.replace(/T|Z/g, ' ') } }, methods: { fetchData: function () { var xhr = new XMLHttpRequest() var self = this xhr.open('GET', apiURL + self.currentBranch) xhr.onload = function () { self.commits = JSON.parse(xhr.responseText) console.log(self.commits[0].html_url) } xhr.send() } } } </script>
decoratorでClass-basedで書いてみよう
<script> import { Vue, Component, Prop } from 'vue-property-decorator' @Component export default class YourComponent extends Vue { @Prop(Number) readonly propA: number | undefined @Watch('child') onChildChanged(val: string, oldVal: string) {} @Emit() onInputChange(e) { return e.target.value } } </script>
まだ微妙?
Composition APIを使おう
<template> <div> <p>{{text}}</p> <button @click="increment"> Count is: {{ state.count }}, double is: {{ state.double }} </button> </div> </template> <script> import { reactive, computed } from 'vue' export default { props: { text: {}, isOpen: {type: Boolean, default: false}, }, setup(props) { const state = reactive({ count: 0, double: computed(() => state.count * 2) }) function increment() { state.count++ } return { props, state, increment } } } </script>
実際にやってみよう!
ライフサイクルフック
beforeCreated ⇒ setup
created ⇒ setup
beforeMount => onBeforeMount
updated => onUpdated
beforeDestroy => onBeforeUnmounted
destoryed => onUnmounted
errorCaptured => onErrorCaptured
ライフサイクルフック2
デバッグ用
onRenderTracked
onRenderTriggered
Composition APIの何がいいの?
thisからの脱却
Testableなコードの実現
コードの再利用
Typesciprtの型サポート
Vuexからの脱却(DIの利用)
store
const StoreSymbol = Symbol() export function provideStore(store) { provide(StoreSymbol, store) } export function useStore() { const store = inject(StoreSymbol) if (!store) { // throw error, no store provided } return store }
const App = { setup() { provideStore(store) } } const Child = { setup() { const store = useStore() // use the store } }
グローバルなストアを注入することができた!
プロダクトに導入してみて感想
graphql(vue-apollo)なんかも合わせると情報量が少ない
コード量が少なくてすっきり
自由度が増してクリーンなアーキテクチャの構成、依存関係をどうすればいいのか分からない(勉強中)
自分の関数型プログラミングの知識が薄い
Vueとは...
ありがとうございました
- 投稿日:2020-02-05T11:38:33+09:00
Imageの表示タイミングを揃える
方針
- 画像の取得タイミングを知る
- 画像の表示を切り替える
実装
JQuery
<div class="content" style="display: none;"> <img id="sample1"></img> <img id="sample2"></img> </div>var allImages = $("#sample1,#sample2"); var allImagesCount = allImages.length; var completeImageCount = 0; for(var i = 0; i < allImagesCount; i++){ $(allImages[i]).bind("load", function(){ completeImageCount++; if (allImagesCount == completeImageCount) { $(".content").css('display', 'block'); } }); }
- display vs visibility
visibilityは、要素自体は消えない方が好ましいので、visibilityを使用する。
Vue
img(:src="images" @load="loaded")Vueも同じ要領で
再現
Network conditionsの設定で表示の遅延を再現することができます。
Network conditionsの設定
1.「More tools」 => 「Network conditions」 で、「Network conditions」のタブを開きます。
2.「Network conditions」の「Network throttling」=>「Custom」 => 「Add」へ進みます。
3.「Add」で作成した「My LTE」を設定します。
再度、ロードすると画像の読み込みが遅くなり、遅延が発生する箇所が分かります。
Reference
- 投稿日:2020-02-05T10:45:49+09:00
nuxtjsのthis.$route.queryで配列を保証する
vue router では
?test[]=1
のようなurlパラメータの記載が出来ず
配列は?test=1&test=2
とすると勝手に["1" , "2"]
のように配列として解釈される。https://jp.vuejs.org/v2/guide/migration-vue-router.html#クエリ内配列のための構文-削除
そのためthis.$route.queryの値に配列の形を期待する場合
- 未定義のとき
- 値が1つのとき
- 値が2つ以上のとき
の3パターンを対応しておく必要がある。
(今回はついでに中身をStringからNumberに変換)data() { return { query: { test: this.$route.query.test ? Array.isArray(this.$route.query.test) ? this.$route.query.test.map((v) => Number(v)) : [Number(this.$route.query.test)] : [] } } },とりあえずdataの初期値として使いたかったので上記のようにしてみたが毎回これを書くのはだるいので
nuxtのinject使って切り分けてみる。utils.jsconst convQuery = (value) => { if (value) { if (Array.isArray(value)) { return value.map((v) => Number(v)) } else { return [Number(value)] } } else { return [] } } export default ({ app }, inject) => { inject('convQuery', convQuery) }これをnuxt.config.jsでpluginsに登録すれば
data() { return { query: { test: this.$convQuery(this.$route.query.test) } } },でOK。スッキリ。
- 投稿日:2020-02-05T07:20:41+09:00
[Vue.js]配列の変更が検知できない理由の「JavaScriptの制限」って何よ!
タイトルの
JavaScriptの制限
はこちらに記載されているものです。
リストレンダリング(注意事項) — Vue.js要約すると、
配列に対して直接インデックスの設定、またはlengthプロパティを変更する場合、view
は更新されません。具体的な操作はこちら。
インデックスでアイテムを直接設定するとき。例: vm.items[indexOfItem] = newValue
配列の長さを変更するとき。例: vm.items.length = newLengthその回避策が
Vue.set
かArray.prototype.splice
を使用するというものです。
簡単にできる回避策なので、ふーんって感じで書き換えて終了なのですが、
JavaScriptの制限
が気になったので調べてみました。ざっくり リアクティブシステム
Vue.jsの値の変更の検知の仕組みは、リアクティブシステム1で実現されています。
ざっくり言うと、Vueインスタンス化の際にプロパティに対してリアクティブになるよう、よしなにやってくれるシステムです。こちらの図でいうと、プロパティの変更をgetter/setterをトリガーにしてWatcherで再描画してくれているということです。
んで、
JavaScriptの制限
って何さ!ヒントはここに書いてありました。
リストレンダリング(配列の置き換え) — Vue.js例えば、filter()、concat()、そしてslice() のような、元の配列を変更しませんが、常に新しい配列を返します。
リアクティブシステムは新しい配列を返してくれることを望んでいるんです!
つまり
JavaScriptの制限
というのは、新しい配列を返さない操作
のことを言っているのです。
vm.items[indexOfItem] = newValue
もvm.items.length = newLength
も配列を返しません。なんだそれだけなのか
それだけなんです。
リストレンダリング(変更メソッド) — Vue.js
ここに書かれているメソッドは新しい配列を返すから検知できるんです。まとめ
私の日本語を読む能力が低かったせいで、
JavaScriptの制限
が配列の置き換えの章
に掛かっていることに気づくのに時間がかかってしまいました。(汗)お間違い等ございましたら、ご指摘いただけますと幸いです。
- 投稿日:2020-02-05T07:20:41+09:00
[Vue.js]配列の更新が検知できない理由の「JavaScriptの制限」って何よ!
タイトルの
JavaScriptの制限
はこちらに記載されているものです。
リストレンダリング(注意事項) — Vue.js要約すると、
配列に対して直接インデックスの設定、またはlengthプロパティを変更する場合、view
は更新されません。具体的な操作はこちら。
インデックスでアイテムを直接設定するとき。例: vm.items[indexOfItem] = newValue
配列の長さを変更するとき。例: vm.items.length = newLengthその回避策が
Vue.set
かArray.prototype.splice
を使用するというものです。
簡単にできる回避策なので、ふーんって感じで書き換えて終了なのですが、
JavaScriptの制限
が気になったので調べてみました。ざっくり リアクティブシステム
Vue.jsの値の変更の検知の仕組みは、リアクティブシステム1で実現されています。
ざっくり言うと、Vueインスタンス化の際にプロパティに対してリアクティブになるよう、よしなにやってくれるシステムです。こちらの図でいうと、プロパティの変更をgetter/setterをトリガーにしてWatcherで再描画してくれているということです。
んで、
JavaScriptの制限
って何さ!ヒントはここに書いてありました。
リストレンダリング(配列の置き換え) — Vue.js例えば、filter()、concat()、そしてslice() のような、元の配列を変更しませんが、常に新しい配列を返します。
リアクティブシステムは新しい配列を返してくれることを望んでいるんです!
つまり
JavaScriptの制限
というのは、新しい配列を返さない操作
のことを言っているのです。
vm.items[indexOfItem] = newValue
もvm.items.length = newLength
も配列は返しません。なんだそれだけなのか
それだけなんです。
リストレンダリング(変更メソッド) — Vue.js
ここに書かれているメソッドは新しい配列を返すから検知できるんです。まとめ
私の日本語を読む能力が低かったせいで、
JavaScriptの制限
が配列の置き換えの章
に掛かっていることに気づくのに時間がかかってしまいました。(汗)お間違い等ございましたら、ご指摘いただけますと幸いです。