pdfがiOS13で表示されない。
これはcontents-typeの問題のようだ。サーバ側で修正がいる。 stackoverflow.com
ABC globalに参照するオブジェクト
Vue.observableを使うらしい。
/* eslint-disable */ import Vue from 'vue' /// グローバル変数定義 const state = Vue.observable({ _hoge:"Hoge", get hoge(): string { return this._hoge; }, set hoge(value:string) { this._hoge = value; } }) declare module 'vue/types/vue' { interface Vue { $state: typeof state; } } Vue.prototype.$state = state; export default state;
これでmain.tsにimportしておく。
あとは使いたいファイルでimportして
console.log("globaltest:"+state.hoge);
とか
<p> global var {{ $state.hoge }} </p>
のようにして使える。
ABC v-bindはオブジェクトや関数を渡せる。
よって、使ってほしい関数などを渡すことは可能だった。 validationに使う関数を渡すのに使ってみた。 指定しないときはnullを入れておくようにした。
ABC5 ストア
例題を勉強したサイトを失念してしまった。思い出したらリンクを張りたい‥。
検索して見つかりました。この記事です。
以下はこの記事を自分で実装してみたメモです。
今、カウンター情報を各コンポーネントで共通化したいと考える。
次のようなクラスを生成する。状態としての情報がreactiveになっている点に注意。
import { reactive } from '@vue/composition-api'; export default function counterStore() { const state = reactive({ count:0 }) return { get count() { return state.count; }, increment() { state.count += 1; }, decrement() { state.count -= 1; } } }
そして、このストアを共有するコンポーネントをテンプレートで囲む用のコンポーネントとして、 CounterProviderコンポーネントを作成する。
<template> <div> <slot /> </div> </template> <script lang="ts"> /* eslint-disable */ import { defineComponent, provide } from '@vue/composition-api' import CounterKey from './counter-key'; import counterStore from '../stores/counter'; export default defineComponent({ setup() { /// ストアを生成しキーを設定する。 provide(CounterKey, counterStore()); return {}; } }) </script>
このprovideというのがポイントでこのためにキーを定義しておく。
/* eslint-disable */ import {InjectionKey} from "@vue/composition-api" import {CounterStore} from '../stores/counter'; /// コンポーネント間で共通に使うキーの定義 const CounterKey: InjectionKey<CounterStore> = Symbol('CounterStore'); export default CounterKey;
使うときはこのようにテンプレートを入れ子にする。
<counter-provider> <InjectedDecrementButton /> <InjectedCounterDisplay /> <InjectedIncrementButton /> </counter-provider>
各、入れ子にしたテンプレートではキーをInjectでカウンターを取り出せる。
<template> <span class="count"> {{ count}} </span> </template> <script lang="ts"> /* eslint-disable */ import { defineComponent, inject, computed } from '@vue/composition-api'; import CounterKey from './counter-key'; export default defineComponent({ name:"InjectedCounterDisplay", setup() { const counter = inject(CounterKey); if (!counter) { throw new Error(`${CounterKey} is not provided`); } const count = computed(() => counter.count); return { count } } }) </script>
<template> <button v-on:click="increment"> + </button> </template> <script lang="ts"> /* eslint-disable */ import { defineComponent, inject } from '@vue/composition-api' import CounterKey from './counter-key'; export default defineComponent({ name:"InjectedIncrementButton", setup() { /// ストアを取得 const counter = inject(CounterKey); if (!counter) { throw new Error(`${CounterKey} is not provided`); } return { increment: counter.increment } } }) </script>
<template> <button v-on:click="decrement"> - </button> </template> <script lang="ts"> /* eslint-disable */ import { defineComponent, inject } from '@vue/composition-api' import CounterKey from './counter-key'; export default defineComponent({ name:"InjectedDecrementButton", setup() { /// ストアを取得 const counter = inject(CounterKey); if (!counter) { throw new Error(`${CounterKey} is not provided`); } return { decrement: counter.decrement } } }) </script>
ABC4 composition-api
composition-api
プラグインなのでVue.useを忘れずに。 defineComponentで作る。 setupしてreturnで参照したい変数(ref,reactiveで作る)、関数、computedな関数等を作って返却する。
例
/* eslint-disable */ export default defineComponent({ name: 'Login2', // components: {}, props: { loginMessage: { type: String, required: true // 必須条件 } }, setup(props, context:SetupContext) { const state = reactive({ name:"", pass:"", }) const inputDisabled = computed(()=> { if (state.name.length == 0) { return true; } if (state.pass.length == 0) { return true; } return false; }) const onSubmitted = ()=> { console.log("onSubmited:"+name); context.emit('onSubmitted',{ name:state.name, pass:state.pass }); } return { state, inputDisabled, onSubmitted } } })
propsは型をinterfaceで定義してやってsetupの引数のところに指定しておくと良い。
rxjsとpromise
rxjsの
someObservable.subscrive((result)=>(....))
が
const result = await someObservable.toPromise();
みたいにプロミスに変更してawaitできる。
あとES6から複数値を関数から受け取れるらしい
function some() { return {4,3}; } let {x, y} = some();
AsyncとPromise
async関数はPromisで包んで返してくれる。awaitはpromiseが解決されるまでそこでまってくれる。これをつかうためには結局、その関数はasyncにならないといけない。
環境変数env
process.envに入っている。 NODE_ENV NODE_DEBUG NODE_PATH
.env ファイルを作ってそれを読むようにできる。
process.env.hoehogeでみえるようになる。
AjaxでJSON取得
req.openの2つ目は非同期のフラグ、req.sendはPOSTの場合データが入る。
const req = new XMLHttpRequest(); req.open("GET", "myjson.json", true); req.onreadystatechange = () => { if (req.readyState === 4 && req.status === 200) { const jsonText = req.responseText; const json = JSON.parse(jsonText); this.resultAjax = jsonText; } } req.send(null);
nodeABC
このサイトを読んで勉強した。
typescriptを入れてみた。packageは
{ "name": "myfirstserver", "version": "1.0.0", "description": "my first server", "main": "index.js", "scripts": { "build": "tsc", "serve": "node dist/js/index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "js" ], "author": "KatagiriSo", "license": "MIT", "dependencies": { "@types/express": "^4.17.6", "@types/node": "^13.13.4", "express": "^4.17.1", "typescript": "^3.8.3" } }
tsconfigは
{ "compilerOptions": { /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ "target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ "outDir": "dist/js", /* Redirect output structure to the directory. */ "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "composite": true, /* Enable project compilation */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ "strict": true, /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ /* Additional Checks */ // "noUnusedLocals": true, /* Report errors on unused locals. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ /* Module Resolution Options */ "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "typeRoots": [], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ /* Experimental Options */ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ /* Advanced Options */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ } }
src/index.tsに
import express from "express"; const app = express(); // http://localhost:3030/ const port = 3030 app.get("/", (req, res, next) => { console.log(req.method, req.url) res.json(require('./../json/responce.json')) }); app.listen(port, () => console.log(`click http://localhost:${port}/ !`))
responce用のjsonを dist/json/responce.jsonに
{ "message":"Hello World!" }
ひとまず動いた。
Vue.JS コンポーネントの使い方
簡単な例 components
<template> <div> <p>myConponent</p> </div> </template>
<script> /* eslint-disable */ import { defineComponent, computed, watch } from '@vue/composition-api'; export default defineComponent({ name: 'MyCard', components: {}, props: {}, data: function() {}, created: function() {}, mounted: function() {}, methods: {}, computed: {}, filters: {}, watch: {}, directives: {} }); </script> <style> </style>
としておく。から実装のところはなくて良い。nameのMyCardを使う。
使いたい親は
スクリプト内で
<script> /* eslint-disable */ import { defineComponent, computed, watch } from '@vue/composition-api'; import MyCard from '@/components/MyCard.vue'; export default defineComponent({ name: 'Hoge', components: { 'my-cards': MyCard },
のように、MyCardを<my-cards>として使うようにする。これで親では
<my-cards></my-cards>
として使えるようになる。タグ名はケバブ表記にすること。
親から値を渡したい。 props
子の方でpropsを定義しておく
import { defineComponent, computed, watch } from '@vue/composition-api'; import { bus } from '../views/Hoge.vue'; export default defineComponent({ name: 'MyCard', components: {}, props: { cardValue: { type: String, required: true // 必須条件 }, otherCardValue: { name: String }, chName: String, chAge: Number },
これはcardValueに関しては値を必ず入れる必要があり、ほかはそうでもない。
子はpropを普通の変数のように
<p>{{ cardValue }}</p>
などで参照できる。
実際に親が値を渡しているのは
<my-cards cardValue="fromParent" v-bind:otherCardValue="watchedData" v-on:helloFromChild="handleHelloFromChild" v-on:countUpRequest="handleCountUpRequest" v-bind:chName.sync="myName" v-bind:chAge.sync="myAge" >
otherCardValueの値は親のwatchedDataにバインドされているのでwatchedDataが変わればotherCardValueは変わる。 v-bind:chName.sync="myName"は双方向バインディングで 子から更新の依頼を
localChAge: { get: function() { return this.chAge; }, set: function(val) { this.$emit('update:chAge', val); // syncしている値を更新する }
のように$emitをつかって飛ばしてやる必要がある。
子から親への呼び出し $emit
hello: function() { this.$emit('helloFromChild', 'MyName'); },
親は予め
<my-cards cardValue="fromParent" v-bind:otherCardValue="watchedData" v-on:helloFromChild="handleHelloFromChild"
のように、呼ばれるものを登録しておく必要がある。これでhandleHelloFromChildが呼ばれる。
イベントバスによるやりとり Vueをbusようにする。
親側でbusとするVueを作っておく。
import Vue from 'vue' export let bus = new Vue();// イベントバス用 export default defineComponent({ name: 'Hoge', components: { 'my-cards': MyCard },
親側でcreatedのライフサイクルで何を受け取るか登録する。 $on
created: function() { // イベントバス登録 bus.$on("BusEvent", function (message) { alert(message); }) },
子側でイベントバスに対して$emitすれば連絡が行く。
helloBusEvent: function() { bus.$emit('BusEvent', 'BusEvent!'); },
スロットを使って親からタグをまるごと渡して子のスロット部分にはめる。 slot
子のテンプレートで入れてもらいたいところにslotタグを置く、slotが複数あるときはnameをつける。値を渡したいときは属性をつける(fromChildSlotValue)。
<template> <div> <p>myConponent</p> <div> <slot name="slot1" fromChildSlotValue="ThisIsFromChildSlotValue!"></slot> </div> <div> <slot name="slot2" fromChildSlotValue="ThisIsFromChildSlotValue!"></slot > </div> </div> </template>
親側はスロットになるものを用意し、slotにslot名を入れる。子からもらえる変数はslot-scope="hoge"でまとめてもらえる。今の場合hoge.fromChildSlotValueで参照可能になる。
<my-cards cardValue="fromParent"> <div slot="slot1" slot-scope="props"> <p>slotされた所 {{props.fromChildSlotValue}}</p> </div> <div slot="slot2" slot-scope="props"> <p>slotされた所2! {{props.fromChildSlotValue}}</p> </div> </my-cards>