20210916のvue.jsに関する記事は3件です。

Vueのタグが見えないようにローディング画面を付ける

Vueの規模が大きくなってくると、Vueのロードが完了するまでの間、{{ xxxx }}のようなタグが目立ってくるようになります。 Vueのコンポーネントを使えばうまく回避できるのかもしれませんが、Vueインスタンスと双方向データバインディングだけで満足している私にとっては、少々悩ましいです。 そこで、VueやJavascriptに頼らず、CSSだけでVueのロード前の画面をかぶせるローディング中画面を作ろうかなあと思います。 実際のローディング画面を見たい場合は、以下のWebページを開くと、一瞬だけローディング画面が見れます。 Webページ  https://poruruba.github.io/utilities/ (参考)GitHub  https://github.com/poruruba/utilities やってること Flexパネルを画面全体で覆って、CSSアニメーションを表示させ、Vueのロードが完了したら、Flexパネルをフェードアウトさせる、です。 画面全体を覆うFlexパネルの定義 ロード完了したらフェードアウトさせる処理 フェードアウトを開始する処理 ロード中のアニメーションのひな型を選ぶ HTMLにロード中アニメーションのエレメントを挿入する Javascriptにフェードアウト開始の呼び出しを追加する 画面全体を覆うFlexパネルの定義 CSSで以下のように表現します。 public/css/start.css #loader-background { background: #fff; height: 100%; width: 100%; position: fixed; display: flex; top: 0px; left: 0px; z-index: 9999; --sk-color: #00ced1; } heightとwidthを100%にしてます。 ※--sk-colorは後で説明します。 ロード完了したらフェードアウトさせる処理 CSSで以下のように表現します。 public/css/start.css .loader-loaded { animation: fadeout-anim 1s linear forwards; } @keyframes fadeout-anim { 100% { opacity: 0; visibility: hidden; } } 上記にて、CSSアニメーションを使って1秒かけて透明およびhiddenにしてます。 フェードアウトを開始する処理 前のCSSで、loader-loadedのクラスがついていれば、フェードアウトのアニメーションが開始されるようにしました。 なので、Vueのロードが完了したタイミングで、Javascriptから以下を呼び出せばよいです。 public/js/vue_utils.js function loader_loaded(){ const element = document.getElementById("loader-background"); element.classList.add('loader-loaded'); } ロード中のアニメーションのひな型を選ぶ こちらのCSSが単純そうだったので採用しました。 tobiasahlin/SpinKit デモページもありますので、どんなアニメーションか確認できます。 CDNにも登録されているのですぐに使えます。 public/index.html <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/spinkit/2.0.1/spinkit.min.css" /> 例えば、以下のようなHTMLを追加すればよいようです。 <div class="sk-chase"> <div class="sk-chase-dot"></div> <div class="sk-chase-dot"></div> <div class="sk-chase-dot"></div> <div class="sk-chase-dot"></div> <div class="sk-chase-dot"></div> <div class="sk-chase-dot"></div> </div> HTMLにロード中アニメーションのエレメントを挿入する <html> の <body> の先頭あたりに以下を追加します。 上記のアニメーションを使う場合 public/index.html <div id="loader-background"> <div class="sk-chase sk-center"> <div class="sk-chase-dot"></div> <div class="sk-chase-dot"></div> <div class="sk-chase-dot"></div> <div class="sk-chase-dot"></div> <div class="sk-chase-dot"></div> <div class="sk-chase-dot"></div> </div> </div> 要するに、idが「loader-background」をもったdivエレメントの中にさきほどのアニメーションの定義を記載するということです。 そのとき、classに「sk-center」を付けてあげます。そうすると、アニメーションが画面中央で動いてくれるようになります。 また、FlexパネルのCSS指定のところで「--sk-color: #00ced1;」というCSS変数を追加していました。これは、SpinKitのアニメーションの色の指定です。お好みで色を変えてください。 Javascriptにフェードアウト開始の呼び出しを追加する Vueでのロード完了として、mountedに以下を追加しましょう。 public/js/start.js mounted: function(){ // ・・・ loader_loaded(); // ★これ } おわり 私は、上記をすでに埋め込み済みの以下のテンプレートをいつも使ってます。 poruruba/express_template 以上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

storybook6のcontrolsまとめ

はじめに 本記事では,UIカタログとして利用されるstorybookについて記述します. storybookにはcontrolsと呼ばれる便利機能があり,コンポーネントなどに与えるデータやプロパティをstorybook上で簡単に変更することができます.新たに作ったUIコンポーネントのテストはもちろん,すでに作られたコンポーネントの挙動を理解するためにも大いに役立ちます. storybookのcontrols機能では,前述のように,UIコンポーネントにデータやプロパティを変更できる機能のことです.ここに貼ったgif画像では,bool値であるprimaryの値をスライドボタンで切り替えたり,ボタンのラベルを変更しています.storybookではこのような値の変更方法以外にも,様々な方法が用意されています.本記事はVue.js環境におけるこれらの記述方法を備忘録的にまとめたものです. 本記事では,あくまでcontrolsの記述方法にフォーカスしていますので,storybookそのもののセットアップ方法や概要などを詳しく知りたい方は,公式ドキュメントや,他の方の記事を参照してください.他の方の記事ですが以下の記事は個人的にとてもわかりやすかったです. 参考記事:Vue と CSF によるモダンな Storybook 6 のはじめかた どんな入力方法があるのか? storybook公式ドキュメントのcontrolsの項目では,以下のようにまとめられています. 15種類のControl Typeがあることがわかります. 以降から,storybookをインストールした直後の環境で動くサンプルコードを載せていきます.作成するファイルは全てsrc/stories/配下に置いていきます. それでは一つづつ記述方法と動作を確認してみましょう. boolean boolean booleanでは,文字通りtrue,falseの値を切り替えることができるcontrolです. 動作確認用に,bool値を受け取る,flagというpropsを持つsampleコンポーネントを作成します.flagに渡される値によって表示される文字が変化します. sample.vue <template> <div> <p v-if=flag>true</p> <p v-else>false</p> </div> </template> <script> export default { name: 'Sample', props: { flag: { type: Boolean, required: true, }, }, }; </script> 次に,sample.vueを呼び出すstories.jsファイルを作成します. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { flag: true, // デフォルト値 }; 実際に動作確認してみます. flagのトグルボタンによってコンポーネントへ渡されているデータが変化していることがわかります.<sample v-bind="args" />でargsを渡すことで,flag: trueのデフォルト値を渡しているのです.しかし,実際のところ,最後のPrimary.argsは記述せずともほぼ同様に動作します.これは,storybookが非常に賢いために,呼び出されているsample.vueに定義されているpropsを解析して,その型に適した入力方法を表示してくれるのです.つまり,NumberやString,Objectなどの型を指定したpropsなどは,storiesに呼び出してargsをv-bindするだけで利用できるようになります. Number Number 前項のsample.vueを少し書き加えてみましょう sample.vue <template> <div> <p v-if=flag>true</p> <p v-else>false</p> {{ num }} <!-- 追記部分 --> </div> </template> <script> export default { name: 'Sample', props: { flag: { type: Boolean, required: false, }, num : { // 追記部分 type: Number, default: 0, } }, }; </script> propsに数字を受け取るように書き換えました.実行結果はこんな感じ. Number(range) rengeでは,Number型のインプットをスライドバー形式で操作ができるようになります.通常のNumberとは異なり,必ずstoriesファイルで追記が必要になります. sample.vue <template> <div> {{ rangeNum }} </div> </template> <script> export default { name: 'Sample', props: { rangeNum : { type: Number, default: 0, } }, }; </script> storiesファイルのargTypesプロパティを指定します.今回は,rangeNumという変数をcontrol type:'range'で指定します.デフォルト値を指定したい場合はargsで指定してあげましょう. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, // ここの記述がポイント argTypes: { rangeNum: { control: { type: 'range', }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { rangeNum: 0, // デフォルト値 }; Object Object コンポーネントにObjectを受け取るpropsを用意し,storiesファイルでObject型の変数を渡してあげます.argTypesの記述は必要ありません(もちろん明示的に記述しても構いません). sample.vue <template> <div> {{ sampleObject }} </div> </template> <script> export default { name: 'Sample', props: { sampleObject: { type: Object, required: false, default: {}, }, }, }; </script> sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { sampleObject: { apple: 'red', grape: 'purple', }, }; 実行結果はこんな感じ Array Array ArrayもObjectと同様に,Array型の変数を受け取るpropsを用意してあげて,storiesファイルでpropsにArray型の変数を渡してあげます. sample.vue <template> <div> {{ sampleArray }} </div> </template> <script> export default { name: 'Sample', props: { sampleArray: { type: Array, required: false, default: [], }, }, }; </script> sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { sampleArray: ['a', 'b', 'c'], }; 実行結果はこんな感じ Array(file) ファイルをinputすることもできます(あまり使う機会はなさそう). Arrayのサンプルコンポーネントをそのまま流用して,storiesファイルのみ書き換えていきます.fileの場合はargTypesを記述します. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, // ここがポイント argTypes: { sampleArray: { control: { type: 'file', }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { sampleArray: [], }; 実行結果はこんな感じ enum enumではいわゆる選択式のデータの渡し方を記述できます.6種類の入力方法があります.この6種類は基本的に描き方が同様です.  radio radioでは,storiesファイルのargTypesのtypeにradioを指定し,選択肢をoptionsに配列として記述します. sample.vue <template> <div> {{ fruit }} </div> </template> <script> export default { name: 'Sample', props: { fruit: { type: String, required: false, default: '', }, }, }; </script> sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, argTypes: { fruit: { control: { type: 'radio', // ここと, options: ['apple', 'banana', 'grape', 'orange'], // ここ }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { fruit: 'apple', }; 実行結果はこんな感じ 実際に渡したいデータにラベルを指定したい場合は,argTypesにlabelsを以下のようにオブジェクト形式で記述してあげると実現できます.vueファイルの変更はありません. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, argTypes: { fruit: { control: { type: 'radio', options: ['apple', 'banana', 'grape', 'orange'], labels: { // ここでラベルを指定する apple: 'りんご', banana: 'ばなな', grape: 'ぶどう', orange: 'オレンジ' }, }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { fruit: 'apple', }; 実行結果はこんな感じ inline-radio radioの選択肢を選択肢ごとに改行せずに横並びに表示します.radioの記述方法と同様で,argTypesのtypeをinline-radioにすることで動作します. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, argTypes: { fruit: { control: { type: 'inline-radio', // 変えるのはここだけ options: ['apple', 'banana', 'grape', 'orange'], labels: { apple: 'りんご', banana: 'ばなな', grape: 'ぶどう', orange: 'オレンジ' }, }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { fruit: 'apple', }; 実行結果はこんな感じ 選択肢の数が多い場合やラベルの文字列が長い場合はradio,そうでない場合はinline-radioを使うのがいいかと思います. check checkはradioと記述方法は同様ですが,複数選択が可能で,入力を配列としてコンポーネントに渡します. vueファイルはradioと同様です. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, argTypes: { fruit: { control: { type: 'check', // 変えるのはここだけ options: ['apple', 'banana', 'grape', 'orange'], labels: { apple: 'りんご', banana: 'ばなな', grape: 'ぶどう', orange: 'オレンジ' }, }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { fruit: 'apple', }; 実行結果はこんな感じ inline-check checkの選択肢を選択肢ごとに改行せずに横並びに表示します.checkの記述方法と同様で,argTypesのtypeをinline-checkにすることで動作します. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, argTypes: { fruit: { control: { type: 'inline-check', // 変えるのはここだけ options: ['apple', 'banana', 'grape', 'orange'], labels: { apple: 'りんご', banana: 'ばなな', grape: 'ぶどう', orange: 'オレンジ' }, }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { fruit: 'apple', }; 実行結果はこんな感じ radio同様,選択肢の数が多い場合やラベルの文字列が長い場合はcheck,そうでない場合はinline-checkを使うのがいいかと思います. select selectでは,プルダウン形式で単一の選択肢を行うことができます. 他のenumと同様の記述方法で,argTypesのtypeをselectにすることで動作します. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, argTypes: { fruit: { control: { type: 'select', // 変えるのはここだけ options: ['apple', 'banana', 'grape', 'orange'], labels: { apple: 'りんご', banana: 'ばなな', grape: 'ぶどう', orange: 'オレンジ' }, }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { fruit: 'apple', }; 実行結果はこんな感じ radioとの使い分けは,より選択肢が多い場合にselect,そうでもない時にradioを使うのがいいかと思います. multi-select selectのようなUIで,複数選択できるようにしたものがmulti-selectです.ctrlキーを押しながら選択することで複数選択が出入るようになります. 選択されたデータは配列の形でコンポーネントに渡されます. 他のenumと同様の記述方法で,argTypesのtypeをmulti-selectにすることで動作します. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, argTypes: { fruit: { control: { type: 'multi-select', // 変えるのはここだけ options: ['apple', 'banana', 'grape', 'orange'], labels: { apple: 'りんご', banana: 'ばなな', grape: 'ぶどう', orange: 'オレンジ' }, }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { fruit: 'apple', }; 実行結果はこんな感じ string String コンポーネントにtype: Stringのpropsを追加することで表示することができます.argTypesの指定は必要ありません(明示的に指定しても当然動作します.). sample.vue <template> <div> {{ message }} <!-- 変更部分 --> </div> </template> <script> export default { name: 'Sample', props: { message: { // 変更部分 type: String, required: false, default: '', }, }, }; </script> sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); color colorを用いることで,カラーパレットを使ってカラーコードを指定することができるようになります. argTypesでtypeにcolorを指定することで実現できます. vueファイルはstringと同様です. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, argTypes: { fruit: { control: { type: 'color', // ここで指定 }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); 実行結果はこんな感じ date dateを用いることでカレンダーから日付と時刻を選択することができるようになります. コンポーネントに渡される値はUNIX Time形式になります. argTypesでtypeにdateを指定することで実現できます. vueファイルはstringと同様です. sample.stories.js import Sample from './sample.vue'; export default { title: 'Example/Sample', component: Sample, argTypes: { fruit: { control: { type: 'date', // ここで指定 }, }, }, }; const Template = (args) => ({ components: { Sample }, setup() { return { args }; }, template: '<sample v-bind="args" />', }); export const Primary = Template.bind({}); 実行結果はこんな感じ おわりに この記事ではStoryBook6に用意されているconnrols addonを一通り動かしてみました.これらを組み合わせると非常にリッチなコンポーネントのカタログを作成することができます. storybookをつかった開発にお役立ていただけたら幸いです.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue3とVue2の2パターンでTodoリストを作成してみる。

ただ今、午前2:00ごろ。 何でこんな時間に記事を作成しているかというと、9/16、9/17は00:00~05:00で「Nuxt Nation Conference」が開かれているので、夜ふかしをしています。 Vue3への移行に伴い、どんな変化があったのか。 まずは何となく把握しようと思い、Vue3とVue2の2パターンでTodoリストを作成してみました。 そのソースコードを公開します。 Vue3に踏み込めていないよ!というVueユーザーにも、両者を比較することで概要はつかめるかなと。 Nuxtで記述してます! お願い 本記事執筆者は、実務未経験のプログラミング初学者です。Vue3関連の情報はまだまだ少ないこともあって、記述に間違いや不自然な点はあるかと思います。 コードをそのまま参考にはしないことを推奨します。 Vue3ってこんな感じなんだあ、と思ってもらうことを目的に作成しております。 また気になる点があれば、コメントにて教えていただけると助かります。 Vue3で良くなったこと 簡単にですが、Vue3で改善されたことを記述しておきます。 詳しく知りたい方は、Youtubeに参考になる動画がありますのでご覧下さい。 Vue3とComposition APIの概要を一気に解説 Vue2の制約 ①コンポーネントの肥大化、処理の分散化 ②コードの再利用性 ③Typescriptとの相性 Vue3による改善 ①処理を一箇所にまとめる。 →Vue2だとdataで定義した変数をmethodsなどで使用するわけで、処理が分散しています。 ここらへんのイメージは、URL記載の図を見るとイメージしやすいでしょうか。 Vue.js Vue3ではsetup関数を用いて、一つに処理をまとめることができるようになりました! ②コードの再利用 Vue2で例えばmethodsの処理を他のコンポーネントでも利用したい場合は、Mixinを使う方法がありました。しかし、これが非常に読みにくく、名前の衝突が発生する恐れがありました。Vue3では、これも改善されているようです。 ③Composition API Composition APIの導入により、Typescriptとの相性も良くなりました。 Vue2 Vue2で記述したのが、下記のコードになります。 <script lang="ts"> import Vue from "vue"; type Item = { done: boolean; content: string; } type DataType = { newTodo: string; todos: Item[]; }; export default Vue.extend({ name: "Page", data(): DataType { return { newTodo: '', todos: [] }; }, methods: { //Todoを追加する addNewTodo() { this.todos.push({ done: false, content: this.newTodo, }); this.newTodo = ''; }, //Todoの完了未完了をクリックで切り替える toggleDone(index: number) { this.todos[index].done= true; }, //Todoを削除 deleteTodo(index: number) { this.todos.splice(index); }, //Todoを一括で完了状態にする markAllDone() { this.todos.forEach((todo) => todo.done = true); }, //Todoを一括で削除する deleteAllTodo() { this.todos = []; } }, }); </script> Vue3 Vue3だとこんな感じ。 <script lang="ts"> import { defineComponent, ref } from '@nuxtjs/composition-api' type Item = { done: boolean; content: string; } export default defineComponent({ setup() { //Todoを追加する let newTodo = ref<string>(""); let todos = ref<Item[]>([]); function addNewTodo() { todos.value.push({ done: false, content: newTodo.value, }); newTodo.value = '' } //Todoの完了未完了をクリックで切り替える function toggleDone(index: number) { todos.value[index].done = true } //Todoを削除 function deleteTodo(index: number) { todos.value.splice(index); } //Todoを一括で完了状態にする function markAllDone() { todos.value.forEach((todo) => todo.done = true); } //Todoを一括で削除する function deleteAllTodo() { todos.value = [] } return { newTodo, todos, addNewTodo, toggleDone, deleteTodo, markAllDone, deleteAllTodo }; }, }); </script> 全体のソースコード github Vue3でのルーティング Vue2だとthis.$router.push('/')でルーティングするのですが、Vue3だと下記のような記述になります。 <script lang="ts"> import { defineComponent, useRouter} from '@nuxtjs/composition-api' export default defineComponent({ setup(){ const router = useRouter() function selectVue3() { router.push('/Vue3') } function selectVue2() { router.push('/Vue2') } return { selectVue3, selectVue2 } } }); </script> 感想 初めてVue2を触ったときは独特だなあと思っていたけど、慣れてくると書きやすくて読みやすかったです。 Vue3は慣れてない今の段階でも、しっくりくるものがある。独特さが薄れた気がします。 今後は、computedやcreatedといった他の処理や、vuexについても検証していきたいです。 参考 Why the CompositionAPI? Vue 3 + Composition APIの概要:Todoアプリを作成する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む