知ったこと考えたことをIssueに記録していきます。
- 1トピック1Issue
[2019/01/01] [タイトル]
の形式- Labelはなるべく付ける(複数も可)
- Issueはクローズにしない
知ったこと考えたこと
背景がグラデーションで、Sassのmixinでは対応できないものがあった。もちろんIE11対応あり。
いちばんスターが付いていて、「css-tricks」でも紹介されているClamp.jsを採用した。
結果としては採用したが、IE11(parallels desktop)でclamp: 3
としても2行になってしまったりした(日本語でも英語でも)。CodePenを見ると動いてそうなので、jQuery必須って感じなのか。
2013年から更新が止まっていて、Issueやプルリクエストも溜まっている状態を見ると、やや不安なライブラリかもしれない。
ちなみに「ftellipsis」はIEでうまく動かなかった。
npm i clamp-js
. ellipsis
に対して処理が実行される。
-webkit-line-clamp
に対応のブラウザでは-webkit-line-clamp
を、非対応のブラウザではテキスト自体が切り取られて…
が追加される。
リサイズにも対応していて、元のテキストを保存しているようだ。
import $clamp from 'clamp-js';
const els = document.getElementsByClassName('ellipsis');
Array.from(els).forEach(el => {
$clamp(el, {clamp: 3});
});
window.matchMedia()
はメディアクエリを監視するのに便利。
よく使うだけに関数化しておきたいと思っていた。
メディアクエリの条件をデータとしてどこかに定数化もしておきたかった。
yuheiyさんのreal-world-website-boilerplateを丸パクリしてみた。
const BROWSER_DEFAULT_FONT_SIZE = 16;
export const MEDIA_QUERY_SMALL = `(min-width: ${375 / BROWSER_DEFAULT_FONT_SIZE}em)`;
export const MEDIA_QUERY_MEDIUM = `(min-width: ${768 / BROWSER_DEFAULT_FONT_SIZE}em)`;
export const MEDIA_QUERY_LARGE = `(min-width: ${1024 / BROWSER_DEFAULT_FONT_SIZE}em)`;
export const MEDIA_QUERY_XLARGE = `(min-width: ${1440 / BROWSER_DEFAULT_FONT_SIZE}em)`;
/**
* @desc メディアクエリがロードで判定またはリサイズで判定が切り替わったときに、コールバックで真偽値を返します。
* @link https://github.com/yuheiy/real-world-website-boilerplate/blob/master/src/js/mediaQuery.js
* @param {string} mediaQuery - メディアクエリ文字列
* @param {boolean} layoutChangedCallback - メディアクエリ文字列が一致するかの真偽値
* @example
* import { installMediaQueryWatcher, MEDIA_QUERY_MEDIUM } from './mediaQuery';
* installMediaQueryWatcher(MEDIA_QUERY_MEDIUM, matches => {
* console.log(matches ? 'MEDIA_QUERY_MEDIUM' : 'MEDIA_QUERY_SMALL');
* });
*/
export const installMediaQueryWatcher = (mediaQuery, layoutChangedCallback) => {
const mql = window.matchMedia(mediaQuery);
const listener = event => {
layoutChangedCallback(event.matches);
};
mql.addListener(listener);
layoutChangedCallback(mql.matches);
const uninstall = () => {
mql.removeListener(listener);
};
return uninstall;
};
理想的には、エンティティやユースケースのようなディレクトリで分割したかったが、そこまで厳密に設計する案件がほとんどないので、エントリーポイントと同階層にそういった関数を置いていくことにした。
汎用系関数はutil/foo.js
としてるが、utility.js
としてみてもいいかもしれない。
button > svg
のような構造でフォーカスを移動させると、IEではSVGにもフォーカスされてしまう。
tabindex="-1"
を指定しても効果がなかった。
調べたところ、IEだけfocusable
に対応していて、それがtabindex
よりも優先されてしまうらしかった。
対応としては、<svg focusable="false"></svg>
と指定する。
Twitterで@_yuheiyさんに一覧できるページを教えてもらった。
https://allyjs.io/data-tables/focusable.html
名前 | 責務 | State | props | event | Atomic Design |
---|---|---|---|---|---|
Container Component | その画面の構成を表現し、それ以外の画面との関係性を表現する。 | ◯ | × | × | Pages |
Factory Component | コンポーネントを動的に切り替えるラッパーコンポーネント。:isで指定して、propsでデータを渡す。 | × | ◯ | × | Templates |
ViewModel Component | ある範囲でのプレゼンテーション(View)とロジック(ViewModel)を持ったコンポーネント。単体でも動くが、View Componentに分割してもよい。 | △ | ◯ | × | Organisms |
View Component | 親コンポーネントから受け取ったpropsだけで動作するコンポーネント。親コンポーネントに依存している。繰り返し処理をしたり、イベントに応じて処理が発生する。 | × | ◯ | ◯ | Molecules |
Design Component | デザインの共通化を目的としたコンポーネント。HTMLタグのような役割を持っている。実装はView Componentと同じ。 | × | ◯ | ◯ | Atoms |
名前 | 責務 |
---|---|
store | ルートコンポーネントにVue.use(Vuex)でVuex Storeを注入できる。computedでthis.$store.state.xxxとすることでViewにリアクティブに反映される。 |
getter | Vuex Storeから受け取ったデータを加工するのはViewModelの役割。Getterは複数のViewModelで重複するようなVuex Storeの加工処理を受け持つ。細かな処理はViewModelに任せる。 |
Mutations | Vuex Storeを更新する唯一の方法。コンポーネントでthis.$store.commit(type, payload)を実行すると、typeで渡されたmutationが実行される。payloadでmutationに値を渡すこともできる(オブジェクトを推奨)。非同期処理はActionsでcommitする。 |
Actoins | "mutationを非同期でcommitしたり、複数のmutationをまとめてcommitできる。コンポーネントでthis.$store.dispatch('xxx')を実行するとmutationが実行される。 |
CSS Gridに入門した。
カラムを定義するgrid-template-columns
と、上下左右のギャップ(ガター)を定義するrow-gap
とcolumn-gap
が便利だ。
CSS Gridっぽく使うならgrid-column
とgrid-row
だが、mixinで定義しておくものでもなさそうなので、よく使うグリッドシステムをCSS Gridで作ってみた。
ブレイクポイントの変数
$mq-breakpoints: (
sm: 375px,
md: 768px,
lg: 1024px,
xl: 1440px,
);
column-gap
はデフォルトで指定する。
row-gap
は必要な時に指定する。
.Grid {
display: grid;
grid-template-columns: 1fr;
column-gap: 15px;
@include mq(lg) {
column-gap: 30px;
}
}
.Grid.\-rowGap {
row-gap: 20px;
@include mq(lg) {
row-gap: 40px;
}
}
-1/1 -1/2@md -1/3@lg
のようにカラム数を指定する。
.Grid(class="-1/1 -1/2@md -1/3@lg -rowGap")
.Grid_Item Grid_Item
.Grid_Item Grid_Item
.Grid_Item Grid_Item
.Grid_Item Grid_Item
.Grid_Item Grid_Item
.Grid_Item Grid_Item
.Grid_Item Grid_Item
@mixin equal-column($key: null) {
$columns: $flex-equal-column;
$suffix: "";
@if $key != null {
$suffix: \@#{$key};
}
@each $column in $columns {
.Grid.\-1\/#{$column}#{$suffix} {
grid-template-columns: repeat(#{$column}, 1fr);
}
}
}
/**
* 1/2と1/3のような均等なカラムを生成します。
*/
@include equal-column();
@each $name, $breakpoint in $mq-breakpoints {
@media (min-width: em($breakpoint)) {
@include equal-column($name);
}
}
生成されたCSS。Autoprefixerでベンダープレフィックスを付ける想定。
.Grid.\-1\/1 {
-ms-grid-columns: (1fr)[1];
grid-template-columns: repeat(1,1fr)
}
.Grid.\-1\/2 {
-ms-grid-columns: (1fr)[2];
grid-template-columns: repeat(2,1fr)
}
.Grid(class="-8to4@md")
.Grid_Item Grid_Item
.Grid_Item Grid_Item
.Grid_Item Grid_Item
.Grid_Item Grid_Item
.Grid_Item Grid_Item
.Grid_Item Grid_Item
.Grid_Item Grid_Item
@mixin column($key: null) {
$columns: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 !default;
$suffix: "";
@if $key != null {
$suffix: \@#{$key};
}
@each $column in $columns {
$lastColumn: 12 - $column;
.Grid.\-#{$column}to#{$lastColumn}#{$suffix} {
grid-template-columns: ($column * 1fr) ((12 - $column) * 1fr);
}
}
}
/**
* 6/12と6/12のようなカラムを生成します。
*/
@include column();
@each $name, $breakpoint in $mq-breakpoints {
@media (min-width: em($breakpoint)) {
@include column($name);
}
}
生成されたCSS。
.Grid.\-1to11 {
-ms-grid-columns: 1fr 11fr;
grid-template-columns: 1fr 11fr
}
.Grid.\-2to10 {
-ms-grid-columns: 2fr 10fr;
grid-template-columns: 2fr 10fr
}
以前「Sassの使い方 – 誰にとっても使いやすいCSSにするための工夫」にも書いたが、Sassの&
は使い方を制限したほうがいい。
使ってもいいのは擬似要素と擬似クラス、.is-*
のようなステートだ。参照する&
は常に同じキーセレクター(最初のブレースにあるセレクター)であることが望ましい。
禁止するのは&__element
のようにセレクターを結合して作ってしまうパターンだ。
結合セレクターを使い出すと、縦に長くなって読みにくくなり、入れ子が深くなるごとに&
の中身が変わっていくことが多い。
たとえばJavaScriptで変数の中身が何度も変わってしまうと、コードを追うのが難しくなり、バグが起きやすくなる。これのSass版だと思えばいい。
検索しにくいというデメリットもある。
ブラウザで確認してblock--modifier
の修正が必要だとわかった。検索しても出てこない、&--modifier
になっていたからだ。
書き方としてはDRYかもしれないが、読みやすさと検索しやすさはマイナスになる。block
の修正を1箇所にできるというDRYは、エディターの機能で十分代用できるので、本当に必要なのか考えてみるといい。
個人的に&
を使ったネストの深いSassはまったく読めないので使わない方針だ。
stylelint-scss 3.9.0で結合セレクターを禁止するオプションselector-no-union-class-nameが追加されている。
&-union
、&_union
、&union
のようなセレクターを許可しなくなる。
&.foo
や& p
のような結合していないセレクターは警告されない。
// stylelintrc
"scss/selector-no-union-class-name": true
参照:
Docker for Macはdocker imageを管理するためにDisk imageを持っている。Disk imageはイメージをビルドするたびに少しずつ溜まっていくらしい。
prederenceのDiscタブでDisk imageのサイズが確認できる。
https://gyazo.com/7b1920d89ad1c9604eb0ae863b6ef4fe
Resetタブの「Reset disc image」をクリックすると、すべてのDocker imageとコンテナを削除できる。設定は変わらない。
https://gyazo.com/c618366bbd553d9d1b7030cffed74de3
無事削除できた。
https://gyazo.com/84f06dd0543c3f5996bce79f11ac1349
Disk imageを削除したらsh start.shからやり直す必要がある。
参考記事
https://blog.pinkumohikan.com/entry/cleanup-docker-disk-image
manabuyasuda/website-template#253
「Tree Shaking」とは、webpackなどのバンドルツールが、利用されていないコード(デッドコード)を出力に含めないようにする機能のこと。
import
とexport
構文を使っている(require()
は対応していない)production
モードで実行している"modules": false
にしている(import
とexport
構文をrequire
に変換しない).babelrc
は以下の設定にした。
{
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"useBuiltIns": "usage",
"corejs": 3
}
]
]
}
lodashはES modules(import
とexport
構文)に対応していない。
lodash-esを使うことでTree Shakingの対象に含めることができる。
npm i lodash-es
lodash自体をインポートすると97KBだったのに対して、
import _ from 'lodash-es';
_.map();
必要なモジュールのみインポートした場合は17KBと82.5%の削減ができた。
import { map } from 'lodash-es';
map();
ライブラリを使う場合は、それがES modulesに対応しているかを確認しておくのがよさそう。とくにjQuery時代から使っているものは。
参照:
Vue.jsのページネーションを検索して出てきたvuejs-paginateを実装してみた。
要件
#4 で導入したものをclass構文に書き換えた。
メディアクエリの条件(横幅)を閉じ込められるのでいいかもしれない。
BaseButton.vue
コンポーネントを作ったとする。
タグはa
の時もbutton
の時もある。
VuetifyなどではcreateElement
を使ってタグ名を変更できるようにしていた。
とはいえ、template
の方が見通しがいいので、createElement
を使わない方法を探していたら:is
を使ったサンプルがあった。
HTML側はpropstag
にタグ名を渡すと想定する。
sample-button(tag="button" type="button") Button
sample-button(tag="a" href="#") Button
SFC側はpropsとしてtag
を設定する。
props: {
tag: {
type: String,
requires: false,
default: 'a',
validator(val) {
return ['a', 'button'].includes(val);
},
},
template
に:is
とthis.tag
でpropsを渡す。
<template>
<a
:is="this.tag"
以下のように出力される。
<button data-v-4dee8d32 type="button">Button</button>
<a data-v-4dee8d32 href="#">Button</a>
input
はa
とbutton
と違って閉じタグがないので、パターンには入れないか、v-if
で1つだけ分岐を作って出し分ける。
Moving beyond console.log() — 8 Console Methods You Should Use When Debugging JavaScript and Node
false
ならログを出力するconsole.assert()
console.count()
とconsole.countReset()
console.group()
とconsole.groupEnd()
console.table()
console.time()
とconsole.timeEnd()
console.assert()
console.assert()
は第一引数に真偽値を渡す。true
の場合はログを実行せず、false
の場合に第二引数以降をログに残す。
const isTrue = true;
const isFalse = false;
console.assert(isTrue, 'これは表示されません。');
console.assert(isFalse, { isFalse }); // Assertion failed: {isFalse: false}
console.count()
とconsole.countReset()
console.count()
は特定の文字列がコンソールに記録された回数をカウントする。
console.countReset()
でカウントをリセットする。
const hello = 'Hello';
console.count(hello); // Hello: 1
console.count(hello); // Hello: 2
console.count(hello); // Hello: 3
console.countReset(hello);
console.count(hello); // Hello: 1
console.group()
とconsole.groupEnd()
console.group()
でグループのラベルを渡す。
console.groupEnd()
でそのグループの出力を終了する。
console.group('A to B');
console.log('A');
console.log('B');
console.groupEnd();
console.table()
console.table()
はオブジェクトや配列をテーブル表示する。ソート機能もあり、複雑なデータの把握ができる。
const user = [{ name: 'name1', age: 1 }, { name: 'name2', age: 2 }];
console.table(user);
console.time()
とconsole.timeEnd()
console.time()
で開始、console.timeEnd()
でパフォーマンスを計測する。
Date.now()
よりも正確で細かい結果を返す。
Date.now()
はms単位までしか計測できない。
const start = Date.now();
for (let i = 0; i < 1000000; i++) {
i + i;
}
const diff = Date.now() - start;
console.log(`Time execution with Date.now: ${diff} ms`); // Time execution with Date.now: 3 ms
console.time()
とconsole.timeEnd()
は小数点12桁まで計測できる。
console.time('Time execution with console.time');
for (let i = 0; i < 1000000; i++) {
i + i;
}
console.timeEnd('Time execution with console.time'); // Time execution with console.time: 3.454833984375ms
環境変数をNuxt.jsやLaravel Mixでも使われているcross-envを使用することにした。
上記に加えて、共有しない環境変数をdotenvで管理することにした。
cross-envの利用状況としては、
mode
や、ミニファイの有無など)dotenvの利用状況としては、
https
オプションに証明書のパスを指定するかしないか環境変数を渡す方法として、webpackではwebpack.DefinePlugin
、Nuxt.jsではenv
プロパティがある。
gulpfile.js内でも使えるので、PugなどのJS以外にも利用できる。
コンテンツに都道府県を含むサイトの場合、URLに都道府県名のローマ字やエリア判定で地方名などを変数化して管理する。
変数化しない場合は、修正対応が煩雑になり、JSのデータとロジックが散らばり、ケアレスミスが増えやすくなる。
変数化は変数に都道府県ごとのオブジェクトを設定するのがよさそう。
都道府県コードはid
に、英語読み(ローマ字)はen
に、地方分けはregion
とした。
https://gist.github.com/manabuyasuda/c24b832e11db33625637987815c88964
const PREFECTURES = [
{ id: '1', name: '北海道', en: 'hokkaido', region: '北海道' },
{ id: '2', name: '青森県', en: 'aomori', region: '東北' },
{ id: '3', name: '岩手県', en: 'iwate', region: '東北' },
{ id: '4', name: '宮城県', en: 'miyagi', region: '東北' },
{ id: '5', name: '秋田県', en: 'akita', region: '東北' },
{ id: '6', name: '山形県', en: 'yamagata', region: '東北' },
{ id: '7', name: '福島県', en: 'fukushima', region: '東北' },
{ id: '8', name: '茨城県', en: 'ibaraki', region: '関東' },
{ id: '9', name: '栃木県', en: 'tochigi', region: '関東' },
{ id: '10', name: '群馬県', en: 'gunma', region: '関東' },
{ id: '11', name: '埼玉県', en: 'saitama', region: '関東' },
{ id: '12', name: '千葉県', en: 'chiba', region: '関東' },
{ id: '13', name: '東京都', en: 'tokyo', region: '関東' },
{ id: '14', name: '神奈川県', en: 'kanagawa', region: '関東' },
{ id: '15', name: '新潟県', en: 'niigata', region: '中部' },
{ id: '16', name: '富山県', en: 'toyama', region: '中部' },
{ id: '17', name: '石川県', en: 'ishikawa', region: '中部' },
{ id: '18', name: '福井県', en: 'fukui', region: '中部' },
{ id: '19', name: '山梨県', en: 'yamanashi', region: '中部' },
{ id: '20', name: '長野県', en: 'nagano', region: '中部' },
{ id: '21', name: '岐阜県', en: 'gifu', region: '中部' },
{ id: '22', name: '静岡県', en: 'shizuoka', region: '中部' },
{ id: '23', name: '愛知県', en: 'aichi', region: '中部' },
{ id: '24', name: '三重県', en: 'mie', region: '近畿' },
{ id: '25', name: '滋賀県', en: 'shiga', region: '近畿' },
{ id: '26', name: '京都府', en: 'kyoto', region: '近畿' },
{ id: '27', name: '大阪府', en: 'osaka', region: '近畿' },
{ id: '28', name: '兵庫県', en: 'hyogo', region: '近畿' },
{ id: '29', name: '奈良県', en: 'nara', region: '近畿' },
{ id: '30', name: '和歌山県', en: 'wakayama', region: '近畿' },
{ id: '31', name: '鳥取県', en: 'tottori', region: '**' },
{ id: '32', name: '島根県', en: 'shimane', region: '**' },
{ id: '33', name: '岡山県', en: 'okayama', region: '**' },
{ id: '34', name: '広島県', en: 'hiroshima', region: '**' },
{ id: '35', name: '山口県', en: 'yamaguchi', region: '**' },
{ id: '36', name: '徳島県', en: 'tokushima', region: '四国' },
{ id: '37', name: '香川県', en: 'kagawa', region: '四国' },
{ id: '38', name: '愛媛県', en: 'ehime', region: '四国' },
{ id: '39', name: '高知県', en: 'kochi', region: '四国' },
{ id: '40', name: '福岡県', en: 'fukuoka', region: '九州' },
{ id: '41', name: '佐賀県', en: 'saga', region: '九州' },
{ id: '42', name: '長崎県', en: 'nagasaki', region: '九州' },
{ id: '43', name: '熊本県', en: 'kumamoto', region: '九州' },
{ id: '44', name: '大分県', en: 'oita', region: '九州' },
{ id: '45', name: '宮崎県', en: 'miyazaki', region: '九州' },
{ id: '46', name: '鹿児島県', en: 'kagoshima', region: '九州' },
{ id: '47', name: '沖縄県', en: 'okinawa', region: '九州' },
];
ユースケースとして、2つの関数を用意した。
「都」「府」「県」を除去するnormalize()
と、任意の地方のデータを抜き出すgetRegion()
。
/**
* 「都」「府」「県」を除去します。
* @param {string} name 都道府県名
* @return {string} 都府県を除去した文字列
* @example
* normalize(PREFECTURES[0].name); // 北海道
* normalize(PREFECTURES[1].name); // 青森
* normalize(PREFECTURES[12].name); // 東京
* normalize(PREFECTURES[26].name); // 大阪
* PREFECTURES[26].name; // 大阪府
*/
const normalize = name => name.replace(/都|府|県/g, '');
/**
* 指定した値と同じ地方のデータを取得します。
* @param {string} name
* @return {array} 一致した都道府県の配列
* @example
* getRegion('北海道'); // [0: {id: "1", name: "北海道", en: "hokkaido", region: "北海道"}]
*/
const getRegion = name => {
return PREFECTURES.reduce((result, current) => {
if (name === current.region) {
result.push(current);
return result;
}
return result;
}, []);
};
Material Components for the webのようにCSSカスタムプロパティを使用しているフレームワークがある。
IEはCSSカスタムプロパティ非対応なので、現状では対策が必要。
:root
以外でCSSカスタムプロパティを使っていない場合に使える。JSで動的に変換できる点で優位。
ドキュメントにあるようにインストールする。
npm install css-vars-ponyfill
インポートして実行する。
import cssVars from 'css-vars-ponyfill';
cssVars();
head
タグ内にテスト用の変数を追加する。
<style>
:root {
--color: black;
}
</style>
</head>
body
内にdiv
を追加して反映を確認する。
<body>
<div>div</div>
CSSを追加する。:root
以外での反映を確認するため、div
に--color: red;
を追加した。
:root {
--a: var(--b); /* Chained */
--b: var(--c);
--c: 10px;
}
div {
--color: red;
color: var(--color); /* from <style> */
margin: var(--unknown, 20px); /* Fallback */
padding: calc(2 * var(--a)); /* Nested */
}
IEのみhead
タグ内に以下のようにstyle
タグでインライン出力された。
<style data-cssvars="out" data-cssvars-job="1" data-cssvars-group="1">
</style>
div {
color: black;
margin: 20px;
padding: calc(2 * 10px);
}
div {}
内の--color: red;
は変換されなかった。
Laravel Mixだと以下のように設定する。preserve: false
にすると、var()
は削除される。
JSで動的に追加されたカスタムプロパティは非対応ブラウザで反映されない。
mix
.js('src/assets/js/app.js', 'dist/assets/js/')
.sass('src/assets/css/app.scss', 'dist/assets/css/')
.options({
processCssUrls: false,
autoprefixer: {
options: {
grid: true,
},
},
postCss: [
require('postcss-custom-properties')({
preserve: false
})
],
});
const date = new Date(2012, 1, 1, 13, 1, 0);
console.log(
new Intl.DateTimeFormat('ja', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: true,
}).format(date),
); // => 2012年2月1日水曜日 午後1:01
console.log(
new Intl.DateTimeFormat('ja', {
weekday: 'short',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false,
}).format(date),
); // => 2012/02/01(水) 13:01
完全にフォーマットしきれないところは、replace()
とかで調整が必要そう。
gulp-iconfontを使うと、変更がなくてもビルドごとに差分が出てしまう。
内包しているgulp-svg2ttfのoptions.timestampによるもの。デフォルトがMath.round(Date.now()/1000)
のため、何もしなければ差分が発生する。
Issueにも上がっていた。
要約すると、「gulp-svg2ttfのtimestamp optionを見てね」「0に設定してもいいけど、Gulpを起動した時間に設定するのが最善だよ」「gulpfile.js内でtimestampがあるかの条件分岐を作る方法があるよ」。
フロントエンドでDDD(OOP)を取り入れられないかなーと思って調べてて、このサイトが優しく雰囲気を教えてくれてよかった。
https://nrslib.com/category/programming/ddd/
User
、 UserName
、 PhoneNumber
User
、 Article
User
エンティティ同士を比較するメソッドを UserService
が持つ。これにプラスして、関数型プログラミング(FP)の考え方を取り入れていくといいのかな。
FPとOOPはバッティングするという意見もあるようですが。
テスト段階だが、History APIを使った処理をclassとしてまとめた。
init()
でupdateParameter
が実行されパラメーターを取得するmargeParameter(parameter)
でパラメーター(Object)を結合するregisterPushState()
で履歴を追加するclass
構文はインスタンス化が前提ではないと気づいた。
static
キーワードで静的メソッドにすると、インスタンス変数を変更されてしまうのを避けることができる。
インスタンス化する場合はTabとかAccordionのようなUI処理をするとき、静的にするのは値を不変にして内部処理で完結できる場合。
class
インスタンス化する場合は、初期化時にインスタンス変数を変更できることがメリット。対象の要素を変更するといった場合に使える。Tab.jsみたいな。
その反面、variableClass1.width = 100;
のようにアクセスして上書きすることができてしまう。「プライベートフィールド宣言」という仕様もあるが、Babelを設定しても使えなかった。
export default class VariableClass {
constructor(options) {
const defaultOptions = {
width: 0,
height: 0,
};
this.options = Object.assign(defaultOptions, options);
Object.keys(this.options).forEach(key => {
this[key] = this.options[key];
});
console.log(this.options); // => { width: 0, height: 0 }
console.log(this.width); // => 0
}
}
const variableClass1 = new VariableClass();
const variableClass2 = new VariableClass({
width: 100,
});
console.log(variableClass1.width); // => 0
console.log(variableClass2.width); // -> 100
variableClass1.width = 100;
console.log(variableClass1.width); // => 100
static
メソッドで動的なclass
getterを設定することで変数を取得することができる。設定しなければプライベート変数になるのでアクセスできない。
class
ブロックの中はメソッドしか設定できないので、const
などを入れることはできない。
const width = 0;
export default class StaticClass {
static get width() {
return width;
}
}
import StaticClass from './StaticClass';
console.log(StaticClass.width); // => 0
setterも設定すると変数を上書きすることもできる。
let width = 0;
export default class StaticClass {
static get width() {
return width;
}
static set width(prop) {
width = prop;
}
}
StaticClass.width = 100;
console.log(StaticClass.width); // => 100
setterを設定せずにStaticClass.width = 100;
とした場合は、Uncaught TypeError: Cannot set property width of function StaticClass()
のようにエラーが返る。
内部の値は空のオブジェクトから初めて、初期化時にローカルストレージの値に上書きする。
インスタンス時の引数に値が上書きされる。初期値とローカルストレージの値をマージした方がいい?
残したおいた記録を元にQiitaに投稿した。
https://qiita.com/manabuyasuda/items/0971dbd3729cf68f87fb
border
の見た目をposition: absolute;
で配置するようなイメージ。
以下のような条件の場合に使うといい。
::before
と::after
は使っているpadding-bottom;
で余白を入れてうえでborder-bottom
を指定したいposition: absolute;
で配置しているので、padding-bottom;
を指定するとズレてしまう.Heading {
box-shadow: 0px 10px 0px 0px #fff, 0px 12px 0px 0px #aaa;
}
border-bottom: 12px solid #aaa
、1つ目でborder-bottom: 10px solid #fff
を指定しているイメージ注意点
border
と違い、box-shadow
はボックスモデルに含まれないbox-shadow
を入れたら、margin-bottom
にはbox-shadow
分を足した値にする必要がある必要なモジュールだけをインポートするのが最適解とはいえ、楽をしたいのもの。
Tree Shakingでいい感じに最適化してくれないかなとテストをした。
すべて_.map();
と同等の処理をしている。
import | ファイルサイズ |
---|---|
import _ from 'lodash-es'; | 96KB |
import { map } from 'lodash-es'; | 16KB |
import * as _ from 'lodash-es'; | 25KB |
意外なことに、import * as _ from
で_
にモジュールをすべて含めるパターンが{ map }
のように個別にインポートするパターンとそれほど大差がない。
_.cloneDeep();
と_.omit();
を追加して再テストした。
import | ファイルサイズ |
---|---|
import _ from 'lodash-es'; | 96KB |
import { map, cloneDeep, omit } from 'lodash-es'; | 23KB |
import * as _ from 'lodash-es'; | 32KB |
一括 / 個別 *100%で計算すると、_.map()
だけの場合は156%大きかったのが、3つになると139%になっていた。
実数だと1つだけの場合と3つの場合で共に9KBしか変わらない。
合計6つにしても10KB(64と74)しか変わらない。
一括でインポートする場合もTree Shakingの対象になっていて、10KB増えているのは_
プロパティにlodashをインポートする処理なのではないか。
import * as _ from 'lodash-es';
を使うのが、パフォーマンスを含めた最適解かもしれない。
気になったのはモジュールを6つ使って64KBって、フルサイズの96KBとそんなに変わらないのでは…。
lodashをフルで入れた場合で80KBだった。
もうlodashでいいのではという気もしてきた。
debounceとthrottleくらいしか使ってない場合はlodash-es、値を色々フォーマットする場合はlodashを使うのがよさそう。
タグの説明はMDNを参照。
優先度は、1が必須、2が任意、3が不要。
親要素 | 用途 | 子要素 | 優先度 | WordPress | MT |
---|---|---|---|---|---|
h1, h2, h3, h4, h5, h6 | HTML の h1–h6 要素は、セクションの見出しを6段階で表します。 h1 が最上位で、 h6 が最下位です。 | a, codeなど | 1 | ○ | ○ |
hr | HTML の hr 要素は、段落レベルの要素間において、テーマの意味的な区切りを表します。例えば、物語のシーンの切り替えや、節における話題の転換などです。 | なし | 1 | ○ | ○ |
ol | HTML の ol 要素は、項目の順序付きリストを表し、ふつうは番号付きのリストとして表示されます。 | li, ol, ul | 1 | ○ | ○ |
p | HTML の p 要素は、テキストの段落を表します。 | a, img, strongなど | 1 | ○ | ○ |
ul | HTML の ul 要素は、項目の順序なしリストを表します。一般的に、行頭記号を伴うリストとして描画されます。 | li, ol, ul | 1 | ○ | ○ |
a | HTML の a 要素 (アンカー要素) は、別のウェブページ、ファイル、同一ページ内の場所、電子メールアドレス、または他の URL へのハイパーリンクを作成します。 | なし | 1 | ○ | ○ |
br | HTML の br 要素 は、文中に改行(キャリッジリターン)を生成します。詩や住所など、行の分割が重要な場合に有用です。 | なし | 1 | ○ | ○ |
em | HTML の em 要素は、強調されたテキストを示します。em 要素は入れ子にすることができ、入れ子の段階に応じてより強い程度の強調を表すことができます。 | なし | 1 | ○ | ○ |
strong | HTML の強い重要性要素 (strong) は、内容の重要性、重大性、または緊急性が高いテキストを表します。ブラウザーは一般的に太字で描画します。 | なし | 1 | ○ | ○ |
img | HTML の img 要素は、文書に画像を埋め込みます。これは置換要素です。 | なし | 1 | ○ | ○ |
iframe | HTML のインラインフレーム要素 (iframe) は、入れ子になった閲覧コンテキストを表現し、現在の HTML ページに他のページを埋め込むことができます。 | なし | 1 | × | × |
table | HTML の table 要素は表形式のデータ、つまり、行と列の組み合わせによるセルに含まれたデータによる二次元の表で表現される情報です。 | thead, tbody, tfoot, caption, th, td | 1 | × | × |
blockquote | HTML の blockquote 要素 (HTML ブロック引用要素) は、内包する要素の文字列が引用文であることを示します。通常、字下げを伴ってレンダリングされます (整形方法については注意の項を参照してください)。 cite 属性により引用元の文書の URL を、 cite 要素により引用元の文書のタイトルなどを明示可能です。 | p, cite, footerなど | 1 | ○ | ○ |
pre | HTML pre 要素は、整形済みテキスト (preformatted text) を表します。この要素内のテキストは一般的に、ファイル内でのレイアウトをそのまま反映して等幅 ("monospace") フォントで表示されます。この要素内のホワイトスペース文字はそのまま表示します。 | code | 1 | ○ | × |
code | HTML の code 要素は、コンピューターコードの短い断片の文字列であると識別できるような外見のコンテンツを表示します。 | なし | 1 | ○ | × |
del | HTML の del 要素は、文書から削除された文字列の範囲を表します。 | なし | 1 | ○ | ○ |
ins | HTML の ins 要素は、文書に追加されたテキストの範囲を表します。 | なし | 1 | ○ | × |
b | HTML の注目付け要素 (b) は、要素の内容に読者の注意を惹きたい場合で、他の特別な重要性が与えられないものに使用します。 | なし | 2 | × | × |
small | HTML の small 要素は、テキストのフォントサイズをブラウザーの最小フォントサイズを限度として、一段階縮小します (例えば large から medium へ、 small から x-small へ)。 HTML5 において、表示上のスタイルとは関係なく、この要素は著作権表示や法的表記のような、注釈や小さく表示される文を表すために再提案されました。 | なし | 2 | × | × |
sub | HTML の 下付き文字要素 (sub) は、表記上の理由で下付き文字として表示するべき行内文字列を指定します。 | なし | 2 | × | × |
sup | HTML の 上付き文字要素 (sup) は、表記上の理由で上付き文字として表示するべき行内文字列を指定します。 | なし | 2 | × | × |
figure | HTML の figure 要素は、図表などの自己完結型のコンテンツを表す要素であり、多くの場合、キャプション(figcaption)と一緒に使用され、ふつう1つの単位として参照されます。 | img, figcaption | 2 | × | × |
kbd | HTML のキーボード入力要素 (kbd) はキーボード、音声入力、その他の入力端末からのユーザーによる文字入力を表す行内の文字列の区間を表します。 | kbd | 2 | × | × |
ruby | HTML の ruby 要素は、ルビ文字による注釈を表します。ルビ文字による注釈は、東アジアの文字の発音 (振り仮名) を表すためのものです。 | rp, rt | 2 | × | × |
s | HTML の s 要素は取り消し線を引いた文字列を表示します。 s 要素はすでに適切または正確ではなくなった事柄を表現します。しかし、文書の修正を示す場合、 s 要素は適切ではありません。この場合は del と ins の方が適しているので、こちらを使用してください。 | なし | 2 | × | × |
samp | HTML のサンプル要素 (samp) は、コンピュータープログラムからのサンプル出力を表す行内文字列を含めるために使用されます。 | なし | 2 | × | × |
abbr | HTML の略語要素 (abbr) は略語や頭字語を表します。任意で title 属性で、略語の完全形または説明を提供することができます。 | なし | 3 | × | × |
i | HTML の i 要素は、何らかの理由で他のテキストと区別されるテキストの範囲を表します。例えば、技術用語、外国語のフレーズ、架空の人物の思考などです。英文においてはよく斜体で表示されるものです。 | なし | 3 | × | × |
mark | HTML の文字列マーク要素 (mark) は、周囲の文脈の中でマークを付けた部分の関連性や重要性のために、参照や記述の目的で目立たせたり強調したりする文字列を表します。 | なし | 3 | × | × |
q | HTML の q 要素 は、その内容が行内の引用であることを表します。最近の多くのブラウザーでは、文字列を引用符で囲むように実装しています。 | なし | 3 | × | × |
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.