20210730のvue.jsに関する記事は7件です。

Vue CLI で yup を IE11 でも動くようにビルドする

バージョン @vue/cli-service: 4.5.0 yup: 0.32.9 問題 yup 0.32 系はアロー関数が使われており、そのままでは IE11 では動きません。 下記のコメントの通り、自分たちのビルドプロセス上で yup をビルドする必要があります。 For folks that continue to need IE 11 support, you have my sympathies! You can continue to use yup by compiling it down further as part of your build process. Tools like create-react-app will do this automatically. 設定 vue.config.js に transpileDependencies の設定を追加しビルド対象に追加できます。 module.exports = { transpileDependencies: ["yup"], }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Vue.js+Vuetify]段階評価ボタン ~評価項目の数と評価対象の数に応じて動的に表示する~

概要 v-btn-toggleで生成した画像のような段階評価ボタンをコンポーネント化し、評価項目の数だけイテレートする。 今回の使用例 生徒一人ひとりの各教科の成績を7段階評価するシステム。 生徒と科目のデータは外部入力などで取得する動的な値。 イメージ コンポーネント構成 孫: EvaluationItem.vue 一組のトグルボタン 科目の数だけ表示する。 子: EvaluationList.vue 複数のトグルボタンのリスト 生徒の数だけ表示する。 親: index.vue  孫コンポーネント(トグルボタンコンポーネント) EvaluationItem.vue <template> <v-btn-toggle v-model="value" @change="sendValue" > <v-btn v-for="n in 7" :key="n" :value="n" > {{ n }} </v-btn> </v-btn-toggle> </template> <script> export default { name: 'EvaluationItem', data() { return { value: null } }, methods: { sendValue() { this.$emit('catch-value', this.value) } } } </script> 1~7の数字が書かれたボタン。この数字は評点(value)とバインドしている。 ボタンが押される(changeイベント)のたびにvalueがリストコンポーネントに送られる 子コンポーネント(リストコンポーネント) EvaluationList.vue <template> <div v-for="(subject, index) in subjects" :key="index" > {{ subject }} <EvaluationItem @catch-value="sendData(index, $event)" /> </div> </template> <script> import EvaluationItem from './EvaluationItem.vue' export default { name: 'EvaluationList', components: { EvaluationItem }, props: { subjects: { type: String, required: true } }, data() { return { evalListData: [] } }, methods: { // リスト内の全ての科目の評点がつけられたかを検証するメソッド isInputDataEnough(arr) { const l = arr.filter(v => v).length // filterによって空要素が除去される return l == this.subjects.length ? true : false // 空要素を除去した後の要素数が科目数と等しければ全て評点がつけられたということ }, sendData(index, value) { // 送られてきた評点を表示順に配列に格納し、全部揃い次第親クラスに配列を送る this.evalListData[index] = value if (this.isInputDataEnough(this.evalListData)) { this.$emit('catch-data', this.evalListData) } } } </script> リスト内で科目の数だけトグルボタンコンポーネントがイテレートされており、それぞれの上に科目名subjectが表示されている。 科目の配列subjectsは親コンポーネントから渡されている。 トグルボタンコンポーネントでchangeイベントのたびに評点が送られてくるとともに、sendDataメソッドが発火する。 それぞれのトグルボタンコンポーネントのリスト内における表示順indexと評点valueが渡されており、評点はその科目の表示順通りに配列evalListDataに格納される。 全ての科目の評点がつけられたとき、評点を格納したevalListDataが親コンポーネントに送られる。 親コンポーネント(ページコンポーネント) index.vue <template> <v-container> <div v-for="(student, index) in students" :key="index" > {{ student }} <EvaluationList :subjects="subjects" @catch-data="setEvalDataCollection(index, $event)" /> </div> </v-container> </template> <script> import EvaluationList from './components/EvaluationList.vue' export default { components: { EvaluationList, }, data() { return { evalDataCollection: [], } }, computed: { subjects() { return // 科目(動的な値) }, students() { return // 生徒(動的な値) } }, methods: { setEvalDataCollection(index, array) { // 複数のリストコンポーネントから送られてきた評点配列たちを表示順通りに格納 this.evalDataCollection[index] = array } } } それぞれのリストで全ての科目の評点が終わり次第、リストコンポーネントから評点が格納された配列が送られてきて、setEvalDataCollectionメソッドが発火する。 それぞれのリストコンポーネントのページ内における表示順indexと評点配列arrayが渡されており、arrayは表示順通りに配列evalDataCollection内に格納される。 students = ['佐藤', '井口', '新井'] subjects = ['国語', '算数', '理科'] のとき evalDataCollection = [ [佐藤の国語の評点, 佐藤の算数の評点, 佐藤の理科の評点], [井口の国語の評点, 井口の算数の評点, 井口の理科の評点], [新井の国語の評点, 新井の算数の評点, 新井の理科の評点] ]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelから受け取ったデータをVueで非同期で更新する。

はじめに LaravelからVueにデータを渡すときのメモを大まかに書いておきます。 環境 Laravel 8.33.1 vue: 2.5.17 api.phpに書くのが正しいのかweb.phpに書くのがいいのかわからないのですが、どちらでも動く、違いといえばapi/をつけるかどうかくらいにしか理解できていないです。。 web.php Route::get('/', [ProductController::class,'index']); Route::get('/Products', [ProductController::class,'getProducts']); テーブル $table->id(); $table->string('name'); $table->string('description'); $table->timestamps(); Resourceをつくって必要なデータだけを取り出します。 php artisan make:resource ProductResource Resourceを書き換え。timestampsは必要ないので取り除いてる。 public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->word, 'description' => $this->description, ]; //デフォルト↓ // return parent::toArray($request); } ProductController //useを追加 use App\Models\Product; use App\Http\Resources\ProductResource; //viewを返す public function index() { return view('index'); } //Vueにデータを渡す public function getProducts() { return ProductResource::collection(Product::all()); } View。appで囲む。script を忘れずに書く <div id="app"> <product-page/> </div> <script src="{{ asset('js/app.js') }}"></script> Laravelからのデータをaxiosで受け取る。受け取ったデータを空の配列のproductsに入れる。for文で回す <template> <div > <p v-for="product in products" :key='product.id'> {{ product.name}}     {{ product.description}} </p> </div> </template> <script> export default { data: function () { return { products: [], }; }, mounted() { this.loadEnglishWord(); }, methods: { //Laravelからのデータをaxiosで受け取る loadProducts: function () { axios .get("/products") .then((response) => { // console.log( response) this.products= response.data.data; }) .catch(function (error) { console.log(error); }); }, }, }; </script>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【vue.js】npm run devでストア(store.js)を動かせるようになるまで

store.jsがどうしても動かなかった Vue.jsの初学者として猫本を進めることしばらく、Vuexを導入しp255以降のstore.jsを実装する段に到達。まずはシンプルなものをとS42 シンプルなストア構造に挑戦しました。 が、動かない。コマンドラインでいくらnpm run devしてもエラーを吐くばかり。 最終的には解決して結構しょうもないオチだったものの、苦しめられたので記録しておきます。同様の事例はあれど解決ログはなさそうだったので。 インストールまで まず猫本p254までの記載通り、npmで一通りvuex関連のinstallを済ませます。すると「my-app」ディレクトリが作成されます。今回変更が必要なのは、その中の「src」ディレクトリだけです。 src直下にあるmain.jsを変えないまま、my-appでコマンドプロンプトを起動しnpm run devを打つと、http://localhost:8080/#/でwebサーバーが立ち上がります。V字マークのページが表示されれば成功です。 その時点のmain.jsのソース。 // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' }) store.jsの作成とmain.jsの修正 そしてp255の『シンプルなストア構造』へ。 今回あまりにも動かなかったので、猫本サポートページやVuex公式ドキュメント、その他様々な記事を見ながら格闘していました。 そして出来上がった動かない版のmain.jsとstore.jsがこちら。 main.js // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' //import store from './store.js' // ここを追記 Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', store, // ここも追記 router, components: { App }, template: '<App/>' }) import store from '@/store.js' console.log(store.state.count) // -> 0 // incrementをコミットする store.commit('increment') // もう一度アクセスしてみるとカウントが増えている console.log(store.state.count) // -> 1 store.js import 'babel-polyfill' import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) // ストアを作成 const store = new Vuex.Store({ state: { count: 0 }, mutations: { // カウントアップするミューテーションを登録 increment(state) { state.count++ } } }) export default store エラーメッセージ ERROR Failed to compile with 1 errors 13:31:58 error in ./src/main.js Module build failed: Error: ENOENT: no such file or directory, open 'C:\Users\suer\Pictures\ITエンジニアスキル\Vue.js\ コード\my-app\src\main.js' @ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/main.js WAIT Compiling... 13:32:05 10% build 30 18 65% buil 95% emitting WARNING Compiled with 2 warnings 13:32:06 ✘ http://eslint.org/docs/rules/space-before-function-paren Missing space before function parentheses src\store.js:13:14 increment(state) { ^ ✘ http://eslint.org/docs/rules/eol-last Newline required at end of file but not found src\store.js:18:21 export default store ^ ✘ 2 problems (2 errors, 0 warnings) Errors: 1 http://eslint.org/docs/rules/space-before-function-paren 1 http://eslint.org/docs/rules/eol-last ✘ http://eslint.org/docs/rules/spaced-comment Expected space or tab after '//' in comment src\main.js:6:1 //import store from './store.js' // ここを追記 ^ ✘ http://eslint.org/docs/rules/indent Expected indentation of 2 spaces but found 0 src\main.js:13:1 // store, // ここも追記 ^ ✘ https://google.com/#q=import%2Ffirst Import in body of module; reorder to top src\main.js:19:1 import store from '@/store.js' ^ ✘ 3 problems (3 errors, 0 warnings) Errors: 1 http://eslint.org/docs/rules/spaced-comment 1 http://eslint.org/docs/rules/indent 1 https://google.com/#q=import%2Ffirst You may use special comments to disable some warnings. Use // eslint-disable-next-line to ignore the next line. Use /* eslint-disable */ to ignore all warnings in a file. エラー要因と解決 結論から言いますと、空白行の不足や空白の入れ方によるものでした。 なんでも検索しているうちにESLintというのが引っ掛かりまして、これは静的検証ツールだそうです。確かにパッケージインストールの際にそんなものを入れたような気もします。 これがスタイルの統一を求めるため、空白の入れ方をエラーとして検知していたようです。なので以下の動作版も、見た目は特にエラー版と変わりありません。 なおコピペした場合最終行の空白行が消えてしまったりしてエラーになることがあります。猫本や公式ページから移してきても動かない、おかしいな……というのはその辺りが原因でした。また、// でのコメントアウトも何故か弾かれるようで、/* */と書く必要があります。 main.js // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import store from './store.js' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', store, router, components: { App }, template: '<App/>' }) store.commit('increment') console.log(store.state.count) store.js import 'babel-polyfill' import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) // ストアを作成 const store = new Vuex.Store({ state: { count: 0 }, mutations: { // カウントアップするミューテーションを登録 increment (state) { state.count++ } } }) export default store 半角スペースを二回入れている箇所にも指摘が入ったりしていたので、エラーログの言う通りに見ていくと動くようになりました。 本体はなんとなくわかってきたけどライブラリわからん……と唸る前にエラーログはしっかり読もう、という学びですね。 (初記事ですが、ここまで読んでくれた方ありがとうございます。解決の役に立ちましたら幸いです)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue】Jest実行時にCannot read property 'module' of undefined【Jest】

環境 Vue 2.6.11 cli-plugin-unit-jest 4.5.0 発生したエラー $ yarn workspace web-card vue-cli-service test:unit ● Test suite failed to run TypeError: Cannot read property 'module' of undefined ...  該当のテストコード login.spec.ts import Test from './component/Test.vue'; test('test Test Component', () => { console.log(Login); // 本来はここにテストコードを書く }); テストコードは、本記事の本筋から逸れてしまい、長くなるので載せていません。あしからずorz 1行目のimportがうまくいってないようです。 解決方法 まず、大前提として、importのパスが正しいか、import先でexportがされているかを確認し、vueファイルが読み込めてないのか?と思い、package.jsonやjest.config.jsの設定を見直しても直らず。。。 そこで下記のGitHub issuesを発見。 tsconfig.json with no compilerOptions causes typescript-compiler to error 下記のように、tsconfig.jsonに"compilerOptions": {}を追加することで直りました。 tsconfig.json { "extends": "../../tsconfig", "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx" ], "exclude": [ "node_modules" ], "compilerOptions": {} }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Building Api Mock Environment

Building Environment express connect-api-mocker axios VueX Impliment Todo App 1. express http://expressjs.com/en/starter/installing.html Hello world example $ npm install express ▼ $ mkdir api $ touch api/index.js ▼ $ vim api/index.js ▼ // api/index.js const express = require('express') const app = express() const port = 8080 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) }) module.exports = { path: '/api', handler: app } ▼ $ vim nuxt.config.js ▼ // nuxt.config.js export default { // ... serverMiddleware: ['../api'] } 2. connect-api-mocker https://github.com/muratcorlu/connect-api-mocker Using with Express $ npm install connect-api-mocker --save-dev ▼ $ vim api/index.js ▼ // api/index.js const express = require('express') const apiMocker = require('connect-api-mocker') const app = express() app.use('/api', apiMocker('mocks/api')) app.listen(8080) module.exports = { path: '/api', handler: app } ▼ Endpoint not found on mock files: Resolution $ mkdir -p __mock__/api/messages $ touch __mock__/api/messages/GET.json ▼ $ vim __mock__/api/messages/GET.json ▼ { "message": "hello, api" } ▼ $ vim api/index.js ▼ // api/index.js // ... app.use('/api', apiMocker('mocks/api', '__mock__/api')) 3. axios https://axios.nuxtjs.org/ Setup $ yarn add @nuxtjs/axios ▼ $ vim nuxt.config.js ▼ // nuxt.config.js export default { // ... modules: ['@nuxtjs/axios'] } Usage $ vim pages/index.vue ▼ // pages/index.vue export default { // ... async asyncData({ $axios }) { const ip = await $axios.$get('/messages') console.log(ip) return { ip } } } ▼ Uncaught (in promise) Error: Request failed with status code 404 Resolution $ vim nuxt.config.js ▼ // nuxt.config.js export default { // ... axios: { prefix: '/api', proxy: true }, proxy: { '/api/': 'http://localhost:8080' } } 4. VueX https://ja.nuxtjs.org/docs/2.x/directory-structure/store モジュール $ mkdir store $ touch store/todos.vue ▼ $ vim store/todos.vue ▼ // store/todos.vue export const state = () => ({ list: [] }) export const mutations = { add(state, text) { state.list.push({ text, done: false }) }, remove(state, { todo }) { state.list.splice(state.list.indexOf(todo), 1) }, toggle(state, todo) { todo.done = !todo.done } } ▼ $ touch pages/todos.vue ▼ $ vim pages/todos.vue ▼ // pages/todos.vue <template> <ul> <li v-for="todo in todos" :key="todo.text"> <input :checked="todo.done" @change="toggle(todo)" type="checkbox"> <span :class="{ done: todo.done }">{{ todo.text }}</span> </li> <li><input @keyup.enter="addTodo" placeholder="What needs to be done?"></li> </ul> </template> <script> import { mapMutations } from 'vuex' export default { computed: { todos () { return this.$store.state.todos.list } }, methods: { addTodo (e) { this.$store.commit('todos/add', e.target.value) e.target.value = '' }, ...mapMutations({ toggle: 'todos/toggle' }) } } </script> <style> .done { text-decoration: line-through; } </style> 5. Impliment Todo App $ mkdir __mock__/api/todos $ touch __mock__/api/todos/GET.json ▼ $ vim __mock__/api/todos/GET.json ▼ { "todos": [ { "text": "aaa", "done": true }, { "text": "bbb", "done": false } ] } ▼ $ vim store/todos.vue ▼ export const state = () => ({ list: [] }) export const mutations = { add(state, data) { const list = Array.isArray(data) ? data : [{ text: data, done: false }] list.forEach(data => { state.list.push(data) }) }, remove(state, { todo }) { state.list.splice(state.list.indexOf(todo), 1) }, toggle(state, todo) { todo.done = !todo.done } } export const actions = { async fetch({ commit }) { const path = `/todos` const { todos } = await this.$axios.$get(path) commit('add', todos) } } ▼ $ vim pages/todos.vue ▼ <template> <div> <ul> <li v-for="todo in todos" :key="todo.text"> <v-checkbox v-model="checkedList" :class="{ done: todo.done }" :label="todo.text" :value="todo.text" @change="toggle(todo)" ></v-checkbox> </li> <li> <v-text-field @keyup.enter="addTodo" placeholder="What needs to be done?"></v-text-field> </li> </ul> </div> </template> <script> import { mapState, mapMutations } from 'vuex' export default { async fetch({ store, params }) { await store.dispatch('todos/fetch') }, created() { this.todos.forEach(todo => { if (todo.done) this.checkedList.push(todo.text) }) }, data() { return { checkedList: [] } }, computed: { ...mapState ({ todos: state => state.todos.list }) }, methods: { addTodo (e) { this.add(e.target.value) e.target.value = '' }, ...mapMutations({ toggle: 'todos/toggle', add: 'todos/add' }) } } </script> <style> .done label { text-decoration: line-through; } </style>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vuexで管理しているデータをCookieに保存して簡単には消えないようにする

※この記事は5分で書きました && 読めます 筆者、Nuxtでグローバルなstate管理にvuexを用いていました。 ログイン情報やユーザー情報をvuexに保存していたのですが、vuexは標準でリロードすると消えてしまうので なんとかブラウザに残したいところでした。 リサーチしてみると、 ・サーバーサイドでセッションを持ってクライアントからリクエストを送りそれを参照する ・(外部プラグイン、モジュールを追加するなどして)vuexのデータを保持する のふたつに分けられるようで後者の場合 ・セッションストレージ ・local storage ・Cookie が選択肢としてありました。 「サーバーサイドでセッションを持ってクライアントからリクエストを送りそれを参照する」について 筆者のケースですが、プロダクトの開発初期でサーバーサイドをプロジェクト分けて開発するのが面倒だったのでNuxt内でフルスタックで開発しています。 どちらにせよBFF(SSR)は持つ予定だったので、一時的にフロントで持つべきでない処理も全て書いています。 つまり、のちのちサーバーサイドは移行する予定で書いています。移行タイミングはかなり不明確です。 設計的にセッションをフロントとバックでどちらで持たせるべきかなど悩んでいましたが、上記事情とフロントでログイン状態を扱うほうが良さそうな気がしたことから一旦この選択肢は捨てました。 vuexのデータを保持する 調べるとvuex-persistedstateを導入する記事が多く目にあたると思います。 英語で「vuex cookie」など検索してもこれが上位に出てきます。 永続化はしたくなくセッションではユーザー体験悪いので、 Cookieだなと決断しましてvuex-persistedstateをyarn add、nuxt.config.jsのmodulesへの追加と公式サンプルのCookie x Universalの例を参考にしてplugins/persistedState.jsを追加します。 pathsのところはvuexのstateに hoge.js export const state () => ({ hoge: '', hogehoge: '', }); など書いていればstore.hogehogeなどでアクセスできると思うので配列に突っ込みます。 keyは'hage'など指定してあげます。Cookieで保存したりsetItemでアクセスする際に用いられるkeyです。 そうすると自分の環境ではうまくいったように感じたのですがしばらくたって確かめてみるとgettersでアクセスできなくなっていました。 調べるとこの記事がありました。 https://noumisoblog.com/vuex-persistedstate-nuxt/#toc4 これで解決できる方もいるかもしれませんが、バリデーション後にaxiosを発火してvuexに保存している自分のケースでは解決できませんでした。 結論 js-cookieを使いましょう。vuexの記述にgetやsetなどをよしなに追加するだけです。 上で挙げた公式サンプルのCookie x Universalの例を見るとわかりますがクライアントだけでcookieを扱う分には特にvuex-persistedstateを使う理由も無いのかと。 これで落ち着いてクッキーを食べられますね。 余談ですが5分で書きましたは嘘でした。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む