10月メモ・リンク集
10月に調べたことのメモです。
Vue, Nuxt 関連
Migrate to Nuxt 2.0
- ts-loader バージョンアップ(Webpack4 に対応)
lang="postcss"
を削除- https://github.com/nuxt/nuxt.js/issues/3231#issuecomment-381885334
because nuxt has enabled postcss-loader in css by default
参考:
- Release Notes - Nuxt.js
- migrate to nuxt 2.0 by Ataww · Pull Request #55 · nuxt-community/typescript-template · GitHub
Nuxt の options.ignore
を利用して pages
内にコンテナやストアを配置
// nuxt.config.js ignore: [ // ... '**/pages/**/{containers,components}/*' ],
メリット:
- 関係のあるコードを近くに配置する
- pages, containers, store の関係をはっきりさせる
- a page has a store and container(s)
変更前のディレクトリ構成:
. ├── containers │ └── foo │ ├── index.vue (<= コンテナコンポーネント) │ ├── components │ ├── store │ └── utils └── pages └── foo └── index.vue (<= ページコンポーネント)
変更後のディレクトリ構成:
. └── pages └── foo ├── index.vue (<= ページコンポーネント) ├── components ├── containers │ └── index.vue (<= コンテナコンポーネント) ├── store └── utils
https://nuxtjs.org/api/configuration-ignore#the-ignore-property
ページ遷移時に権限確認
- Middleware arguments · Issue #1687 · nuxt/nuxt.js · GitHub
- vue-router の
meta
を利用すると綺麗に実装できる
- vue-router の
// middleware // ... // Get authorizations for matched routes (with children routes too) const authorizationLevels = route.meta.map((meta) => { if (meta.auth && typeof meta.auth.authority !== 'undefined') return meta.auth.authority return 0 }) // Get highest authorization level const highestAuthority = Math.max.apply(null, authorizationLevels) // ...
不要なビルド処理を削減
- API: build プロパティ - Nuxt.js
extend メソッドは一度はサーバーのバンドルのため、一度はクライアントのバンドルのため、つまり二度呼び出されます。
webpack.config.js (実装例):
module.exports = (config, options) => { // Add plugins config.plugins.push( // ... ); // Do not run type checking twice. (This config is called twice, // one time for the server bundle, and one time for the client bundle.) if (options.isServer) { config.plugins.push(new ForkTSCheckerPlugin({ vue: true })); } // ... return config; };
文字コード・正規表現
Unicode Property Escapes
- GitHub - tc39/proposal-regexp-unicode-property-escapes: Proposal to add Unicode property escapes
\p{…}
and\P{…}
to regular expressions in ECMAScript. - JavaScriptのUnicode Property Escapesについての補説
- ECMAScript 2018よりRegExpで使えるようになったUnicodeプロパティーエスケープ (\p{...}, \P{...}) についての補説
なおHiraganaとKatakanaはあるのにKanjiがないと思われるかもしれませんが、Han (Hani) というのが漢字のことです(「漢字」の中国語読みをローマ字化したHanziに由来)。
補足:
文字コードの変換
- Unicode Lookup: convert special characters
- 文字を入力すると Hex (16進数) , HTML コードに変換してくれる
latin
,kana
なども
- マルチバイト文字, fromCharCode, charCodeAt, Unicode - ryotah’s blog
'>'.charCodeAt(0).toString(16) => '3e'
,String.fromCharCode(0x3e) => '>'
- JavaScriptでのサロゲートペア文字列のメモ - Qiita
['𩸽'.charCodeAt(0), '𩸽'.charCodeAt(1)].map(num => num.toString(16)); // => ["d867", "de3d"]
パスワード向け正規表現
例: 数字・アルファベット・記号を許容する
- 記号とは
- アスキー文字ならば可能、と定義した場合
サンプル:
// 数字・小文字・大文字・記号を最低1文字含む, 8文字以上64文字以下 /^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!-\/:-@[-`{-~])[!-~]{8,64}$/.test(value);
その他参考:
肯定的先読み
- 言語別:パスワード向けの正規表現 - Qiita
SVG 関連
SVG をアイコンフォントの代替にする
参考記事:
実装例 (Font Awesome):
<svg> <use xlink:href="fa-brands.svg#facebook"></use> </svg>
<?xml version="1.0" encoding="UTF-8"?> <!-- Font Awesome Free 5.5.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> // ... <symbol id="facebook" viewBox="0 0 448 512"> <title id="facebook-title">Facebook</title> <path d="..."></path> </symbol> // ... </svg>
https://fontawesome.com/how-to-use/on-the-web/advanced/svg-sprites
書き出し (WIP):
svgo
で不要タグなどを整理. 色情報消去(fill を空にする)svgo *.svg --disable=removeTitle --config='{ "plugins": [ { "removeAttrs": { "attrs": "fill" } } ], "floatPrecision": xx }'
<symbol id="xxx" viewBox="0 0 xx xx">
を追加 (単体ファイルにする? or SVG Sprite にする?)- svgo で対応する or 別ツールを利用する
アウトプット例:
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg"><title>title</title><symbol id="root" viewBox="0 0 24 24"><path d="..." fill-rule="evenodd"/></symbol></svg>
関連情報
SVG 基礎知識:
- SVG 要素リファレンス - SVG: Scalable Vector Graphics | MDN
- 構造的要素
<defs>, <g>, <svg>, <symbol>, <use>
- 構造的要素
- svg 要素の基本的な使い方まとめ
defs要素は各種定義情報(テンプレートとなる図形やグラデーション等)を格納する.プログラムにおけるサブルーチンを記述する場所に相当する.
use要素はxlink:href属性に設定した要素の内容を元に新しい図形を描画することを示す.
g要素が図形の論理的なひとまとまりを表すのに対し,symbol要素はviewBoxを定義し新たな図形を定義する点が異なる.
- SVGのviewBoxをわかりやすく紐解く | Tech Blog | 株式会社INDETAIL - インディテール
ツール・書き出し:
- GitHub - svg/svgo: Node.js tool for optimizing SVG files
- GitHub - svgstore/svgstore: Combines multiple svg files into one.
- GitHub - jkphl/svg-sprite: SVG sprites & stacks galore — A low-level Node.js module that takes a bunch of SVG files, optimizes them and bakes them into SVG sprites of several types along with suitable stylesheet resources (e.g. CSS, Sass, LESS, Stylus, etc.)
- Workflow for creating SVG sprites with NPM scripts – Oleg Varaksin – Medium
- Preparing and Exporting SVG Icons in Sketch – Design + Sketch – Medium
- Sketchでアイコンを作成 / 書き出しするときの Tips
その他:
JIRA 芸
JIRA 使い始めました。
Form Events
- input - Event reference | MDN
- change - Event reference | MDN
For input elements with type=checkbox or type=radio, the input event should fire when a user toggles the control (via touch, mouse or keyboard) per the HTML5 specification, but historically, this has not been the case.
- html-form-event - StackBlitz
- サンプル
書いた記事
その他
VeeValidate メモ
Vue のバリデーションライブラリ VeeValidate の使い方をまとめたもの。(VeeValidate 2.1.0-beta.11, Vue 2.5.17)
基本的な使い方
<input v-validate="'required|email'" type="email" name="email"> <span>{{ errors.first('email') }}</span>
v-validate
にバリデーションルールを渡す- Validation Rules | VeeValidate と自分で追加可能な Custom Rules | VeeValidate がある
- バリデーションルールを設定しない場合でも VeeValidate が属性から追加のルールを推定する
errors.first
メソッドで入力フィールドのエラーを取得
バリデーションルールのシンタックス
<input v-validate="'required|min:6'" type="password" name="password"> <input v-validate="{ required: true, email: true }" type="email" name="email">
- 文字列かオブジェクトの形式で渡すことができる
カスタムルール
// Function Form Validator.extend('custom', (value, args) => { // Return a Boolean or a Promise that resolves to a boolean. }); // Object Form Validator.extend('custom', { getMessage(field, args) { // will be added to default locale messages. // Returns a message. }, validate(value, args) { // Returns a Boolean or a Promise that resolves to a boolean. } });
getMessage
の引数field
はフィールド名 (String)getMessage
を利用すると現在のロケールの辞書に追加される。多言語対応をする場合は Localization API を利用する。
さらに詳しく
- Custom Rules | VeeValidate
- 引数を必要とするルール・他の入力フィールドと比較をするルール・Non-immediate なルール(
immediate
修飾子が設定されていない場合、初期バリデーションをスキップする)・data
プロパティについて、など
- 引数を必要とするルール・他の入力フィールドと比較をするルール・Non-immediate なルール(
エラーメッセージ
エラーメッセージを変更/追加する
Validator.localize
を利用して辞書 (rootDictionary
) を登録する。
import { Validator } from 'vee-validate'; const dictionary = { en: { messages:{ custom: () => 'Some English Message', } } }; // Override and merge the dictionaries Validator.localize(dictionary); // メモ: メッセージを生成する関数の形式 // function rule (fieldName: string, params: any[], data?: any): string { // return `Some error message for the ${fieldName} field.`; // }
Configuration | VeeValidate を利用して登録することも可。
入力フィールドの名前
エラーメッセージと同様に辞書を更新する。
const dictionary = { en: { attributes: { email: 'Email Address' } }, };
- 以下のようにフィールド名が変更される
- The email field is required. => The Email Address field is required.
data-vv-as
を利用してフィールド名を変更することもできるが、多言語対応するなら辞書を利用した方がいい
さらに詳しく
- Error Messages | VeeValidate
custom
プロパティについて、など
カスタムコンポーネントで使う
- Validating Custom Components | VeeValidate
DEMO:
スコープ
- VeeValidate のバリデータスコープはコンポーネント毎につくられる
- コンポーネントに
inject: ['$validator']
をすることで親のスコープを取得できる - メモリ消費量を抑えるため、バリデータスコープの自動生成をさせないことも可能方法
- 設定変更に関しては Configuration | VeeValidate に詳細がある (
inject: false
) - (自動生成されなくなるので)自身のコンポーネントにバリデータスコープを生成したい場合は以下のように
$_veeValidate
を利用する
- 設定変更に関しては Configuration | VeeValidate に詳細がある (
$_veeValidate: { validator: 'new' }
- 同じコンポーネント内(バリデータスコープ内)でフィールド名がコンフリクトする場合
data-vv-scope
を利用してスコープを作成することができる(コンポーネント毎に生成されるバリデータスコープとは別物)form
タグにdata-vv-scope
を設定すると自動で入力フィールドにも同じスコープが設定される
DEMO:
参考:
- Component Injections | VeeValidate
- With SSR Frameworks like Nuxt, it is recommended to disable automatic injection since it may cause memory leaks due to all the validator instances being created for every component, which is not needed and may slow down your site.
- Scopes | VeeValidate
VueI18n と一緒に使う
設定:
// ... import en from '~/locales/en/validation'; Vue.use(VueI18n); const i18n = new VueI18n(); Vue.use(VeeValidate, { // ... // i18nRootKey: 'validation', 'validation' is default i18n, dictionary: { en } });
利用:
// 言語を変更する場合は `$i18n` から this.$i18n.locale = 'ar';
言語ファイル:
import en from 'vee-validate/dist/locale/en'; // 最終的に VueI18n の言語データとして書き出される export default { // VeeValidate の辞書形式 attributes: { custom: 'Custom', // ... }, messages: { ...en.messages, custom: () => 'Some English Message', }, };
参考:
その他
Validator#validate と Validator#validateAll
validate
に関しては Validator API | VeeValidate にまとまっているが validateAll
に関しては情報が少ない。実際には、引数の形式は違うが機能としては同じものがいくつかある。validator.validateAll()
より validator.validate()
の方が実質の All だったりする。
// validate all fields. validator.validate(); // validate a field that has a matching name with the provided selector. validator.validate('field'); // validate a field within a scope. validator.validate('scope.field'); // validate all fields within this scope. // => 内部で validator.validateAll('scope') を呼ぶ validator.validate('scope.*'); // validate all fields without a scope. // => 内部で validator.validateAll() を呼ぶ validator.validate('*');
DEMO:
Flags
- Flags | VeeValidate
Field
クラスのプロパティflags
, mapFields helper など
DEMO:
export class Field { id: string; name: string; scope: string; flags: FieldFlags; isRequired: boolean; initial: boolean; el: any; value: any; rules: any; update(options:object): void; } export interface FieldFlags { untouched: boolean; touched: boolean; dirty: boolean; pristine: boolean; valid?: boolean; invalid?: boolean; validated: boolean; required: boolean; pending: boolean; }
Validation Events
- vee-validate はデフォルトで
input
イベントをリスニングしている - リスニング対象を変更したい場合、デフォルトの挙動を変更するか、フィールド毎に変更するか、2通りの方法がある
data-vv-validate-on
参考:
- Validation Events | VeeValidate
- data-vv-validate-on Custom Events Not Working · Issue #1381 · baianat/vee-validate · GitHub
入力フィールドが動的に表示/生成される場合
Vue が要素を再利用しないように、ユニークな key
を設定する必要がある。
参考:
Misc.
v-validate:xxx
.immediate
,.continues
,.bails
型定義ファイル
9月メモ・リンク集
9月に調べたことのメモです。
Vue 関連
- What is the best way to access this.$router.push() / router.push() inside the Vuex? · Issue #1384 · nuxt/nuxt.js · GitHub
- v-on to bind dom event in a custom component · Issue #2942 · vuejs/vue · GitHub
<foo @click.native="hello">
- カスタムコンポーネントがネイティブイベントを利用するために
- .sync vs v-model - Vue Forum
- Vue の
.sync
とv-model
について - 基本は同じもの。複数の prop に v-model ロジックを利用したいとう要望のため
.sync
が追加された
- Vue の
- nuxt.js/examples/with-keep-alive at dev · nuxt/nuxt.js · GitHub
ルーティング関連
- Vue Router の公式ガイドを読んだときに試したサンプル
- Vue.js vue-router Nuxt.js の各フック(など)がいつ実行されるかメモ - ryotah’s blog
- ナビゲーション実行時のフックの実行順を確認するためのサンプル
i18n
言語データの整理方法メモ
{ "common": { // 一般的な用語 "action": { "close": "閉じる" }, "label": { "calendar": "カレンダー" }, // ... }, "glossary": { // アプリケーション用語, Domain "task": { "label": { // ... }, }, }, "components": { // Shared Components に対応 "calendar": { // ... }, }, "modules": { // 各ルートに対応 "todo": { // ... }, "todos": { // ... } }, }
- Angular アプリでの例
- 意味のグループと場所のグループ
common
,glossary
=> 意味components
,modules
=> 場所 (View と強く結びつく)
common
,glossary
はどこの View からも呼び出しが可能。
エイリアスが利用できるならcomponents
やmodules
などから利用することも可。- 考慮したいこと
- 翻訳依頼するときに翻訳者がコンテキストを理解しやすいか
- 開発時に不要なメッセージが増えにくいか
- 必要な言語を探しやすいか
- 新しいメッセージをどこに追加するか迷わないか
- 利用していないメッセージを発見しやすいか
その他
Vue.js vue-router Nuxt.js の各フック (など) がいつ実行されるかメモ
続編のようなものを書きました。 ryotah.hatenablog.com
GitHub - ryotah/vue-vue-router-nuxt-hooks
ログに表示される内容:
[INFO] vue: [page] / [hook]
- Vue.js のライフサイクルフック
created
,beforeUpdate
,destroyed
, etc.
[INFO] vue-router: [page] / [guard]
- vue-router のナビゲーションガード
beforeRouteEnter
,beforeRouteUpdate
,beforeRouteLeave
[INFO] nuxt: [page] / [method]
- Nuxt.js の
asyncData
,fetch
- Nuxt.js の
確認できること:
- 以下の遷移
- /hooks/parents/1
- /hooks/parents/2
- /hooks/parents/1/child
- /hooks/parents/2/child
- /hooks/parents/2/child?q=query
- リダイレクトや遷移失敗 (abort) 時の処理
asyncData
/fetch
でページ (state) を初期化、beforeRouteLeave
でページ (state) をリセットした場合の問題点の把握- 今回のモチベーションはこれ
8月メモ・リンク集
8月に調べたことのメモです。
Vue 関連
基礎
- Vue.js 学習メモ - ryotah’s blog
- Vuex 学習メモ - ryotah’s blog
- Nuxt.js 学習メモ - ryotah’s blog
- How to redirect with vue-router? · Issue #1843 · nuxt/nuxt.js · GitHub
- tips
- vue.js - VueJs 2.0 - how to listen for
props
changes - Stack OverflowbeforeUpdate
,updated
でいいかとおもったけどちがった- 上記 hook は
props
に限らない
- 上記 hook は
- Props change will not trigger child component update if props not referred in template · Issue #5325 · vuejs/vue · GitHub
updated
hook means the component did a re-render. If the prop is never used during render, why would you expect the component to re-render when it changes?
- vue.js - What is the difference between updated hook and watchers in VueJS? - Stack Overflow
The lifecycle hooks around update respond to changes in the DOM. Watchers respond to changes in the data.
ちょっと応用
- Vue Mastery
- Evan You on Proxies - Advanced Components | Vue Mastery
- Proxy を利用した場合の話
- Vue のリアクティブシステム - ryotah’s blog
- 動的に Vue インスタンスを append する方法のヒント
- Modal 実装に関して
- Modal - BootstrapVue
- Component | Element
- モーダルコンポーネント — Vue.js
- ミニマムなモーダル
- vue-modal - StackBlitz
- 以下機能を追加したモーダルサンプル
- エスケープキーで閉じる
- 背景(backdrop)クリックで閉じる
show
,shown
,hide
,hidden
イベント発火v-model
を利用した open/hide 操作show()
,hide()
メソッドによる open/hide 操作body
のスクロール防止- (スクロールバーがなくなることによるレイアウトずれに関しては未実装)
- モーダル内にフォーカス固定
- 以下機能を追加したモーダルサンプル
- TypeScript
Angular 関連
- (WIP) Learn Angular - ryotah’s blog
- Angular 学習のためのロードマップ
JavaScript その他
- Proxy
- GitHub - GoogleChrome/proxy-polyfill: Proxy object polyfill
This is a polyfill for the Proxy object, part of ES6. See the MDN docs or Introducing ES2015 Proxies for more information on Proxy itself. Unlike other polyfills, this does not require Object.observe, which is deprecated.
- ECMAScript 2015 の Proxy(Proxies) / Reflect をなんとなく理解する
- GitHub - GoogleChrome/proxy-polyfill: Proxy object polyfill
- Object.observe の死 (ECMAScript の提案取り下げ、V8 からも削除予定) - てっく煮ブログ
- redux Presentational / Container componentの分離 - react-redux.connect()のつかいかた
- ISO 形式 (ISO 8601) の文字列判定 - ryotah’s blog
その他
ISO 形式 (ISO 8601) の文字列判定
ISO 8601は日付と時刻の表記に関する国際規格。
// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString new Date().toISOString() // => "2018-08-31T04:56:23.130Z"
const ISO8601_DATE_REGEX = /^\d{4}-?\d\d-?\d\d(?:T\d\d(?::?\d\d(?::?\d\d(?:\.\d+)?)?)?(?:Z|[+-]\d\d:?\d\d)?)?$/; ISO8601_DATE_REGEX.test('20101010'); // => true ISO8601_DATE_REGEX.test('2010-10-10'); // => true ISO8601_DATE_REGEX.test('2010-10-10T00'); // => true ISO8601_DATE_REGEX.test('2010-10-10T00:00'); // => true ISO8601_DATE_REGEX.test('2010-10-10T00:00:00'); // => true ISO8601_DATE_REGEX.test('2010-10-10T00:00:00.000'); // => true ISO8601_DATE_REGEX.test('2010-10-10T00:00:00.000Z'); // => true ISO8601_DATE_REGEX.test('2010-10-10T00:00:00.000+09:00'); // => true ISO8601_DATE_REGEX.test('2010-1-10'); // => false ISO8601_DATE_REGEX.test('2010-10-10T'); // => false ISO8601_DATE_REGEX.test('2010-10-10T00:00:00000'); // => false
Vue のリアクティブシステム
勉強会で発表した資料です。
Vue のリアクティブシステム、その中でも依存関係のある関数の収集と再実行をどのように実現しているのかについて解説しています。Object.defineProperty, Dep Class and Watcher.
=> モデルの変更がDOMに反映される仕組み --- ![inline](model-dom.png) https://blog.thoughtram.io//angular/2016/02/22/angular-2-change-detection-explained.html --- ![inline](data.png) [リアクティブの探求 — Vue.js](https://jp.vuejs.org/v2/guide/reactivity.html) --- # 一旦サンプルを --- **値段**と**数**から**合計金額**を表示するアプリケーション
<!-- html --> <div id="app"> <div>price: {{ price }}</div> <div>quantity: {{ quantity }}</div> <div>total: {{ total }}</div> </div>
// js const app = new Vue({ el: '#app', data: { price: 100, quantity: 2 }, computed: { total() { return this.price * this.quantity; } } });https://stackblitz.com/edit/vue-reactivity(https://stackblitz.com/edit/vue-reactivity) --- - `data` - Vue インスタンスのためのデータオブジェクト - Vue インスタンスが作成されるとリアクティブシステムに追加される - `computed` - Vue インスタンスに組み込まれる算出プロパティ - 算出プロパティは依存関係にもとづきキャッシュされる --- # 今日のゴールは ---
let data = { price: 100, quantity: 2 }; let total = data.price * data.quantity; console.log(total); // => 200 data.quantity = 3; console.log(total); // => 300 ?--- # その1 ## 関数を保存 ---
let data = { price: 100, quantity: 2 }; // 再計算できるように関数を保存 let target = () => data.total = data.price * data.quantity; target(); console.log(data.total); // => 200 data.quantity = 3; target(); console.log(data.total); // => 300 // https://stackblitz.com/edit/vue-reactivity-step-by-step?file=step-96.js--- - 保存される関数は複数必要 - 依存関係のある関数だけを管理したい --- # その2 ## Dependency Class ---
export let target = null; export class Dep { constructor() { this.subscribers= []; } depend() { if (target && !this.subscribers.includes(target)) { this.subscribers.push(target); } } notify() { this.subscribers.forEach(sub => sub()); } }---
let data = { price: 100, quantity: 2 }; let watcher = () => data.total = data.price * data.quantity; const dep = new Dep(); target = watcher; dep.depend(); target(); target = null; console.log(data.total); // => 200 data.quantity = 3; dep.notify(); console.log(data.total); // => 300 // https://stackblitz.com/edit/vue-reactivity-step-by-step?file=step-97.js--- # Dependency Class の役割 --- ![inline](dep.png) https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d(https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d) --- ![inline](dep-2.png) https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d(https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d) --- ![inline](dep-3.png) https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d(https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d) --- - プロパティごとに `Dep` インスタンスが必要 - 依存関係のある関数だけを管理したい - (未解決) --- # その3 ## `Object.defineProperty` ---
Object.keys(data).forEach(key => { let _value = data[key]; Object.defineProperty(data, key, { get() { console.log('get', key, _value); return _value; }, set(value) { console.log('set', key, _value); _value = value; } }); });---
Object.keys(data).forEach(key => { let _value = data[key]; const dep = new Dep(); Object.defineProperty(data, key, { get() { dep.depend(); return _value; }, set(value) { _value = value; dep.notify(); } }); }); // ... target = watcher; target(); target = null;--- # 完成
console.log(data.total); // => 200 data.quantity = 3; console.log(data.total); // => 300https://stackblitz.com/edit/vue-reactivity-step-by-step?file=step-99.js(https://stackblitz.com/edit/vue-reactivity-step-by-step?file=step-99.js) --- ![inline](data_with_annotations.png) https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d(https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d) --- # 振り返り - Vue のリアクティブシステムの一部を説明 - `Object.defineProperty` - `Dep` class - `Watcher` --- # 参考資料 - [The Best Explanation of JavaScript Reactivity 🎆 – Vue Mastery – Medium](https://medium.com/vue-mastery/the-best-explanation-of-javascript-reactivity-fea6112dd80d) --- # ご静聴ありがとうございました --- # おまけ1 ## Angular の場合 ---
export class AppComponent { price: number; quantity: number; constructor() { this.price = 100; this.quantity = 2; (window as any).app = this; } get total() { return this.price * this.quantity; } } // コンソールから実行 window.app.quantity = 10; // => DOMは更新されない // => ボタンクリックなどをすると反映されるhttps://stackblitz.com/edit/vue-reactivity-case-of-angular(https://stackblitz.com/edit/vue-reactivity-case-of-angular) --- Angular のレンダリングに興味がある方は [日本語訳 Angular 2 Change Detection Explained |