Vueコンポーネント:Bootstrap Modalにスケーリング機能を追加する
6716 ワード
需要
Bootstrapは現在最も流行しているフロントエンドの基礎フレームワークの一つであるべきだ.アーキテクチャの優位性のため、侵入性が低く、さまざまな方法で他のプロジェクトに統合できます.わが工場の各種製品には,みなその活躍の場がある.
先日、ボスはModal(弾窓)が彼のスクリーンに小さすぎて、5 Kディスプレイを浪費していると愚痴をこぼした.
見てみましたが、Bootstrapのデザインで1200 pxを超えるとXLでも
技術案
では、総合的に見ると、最も適切な方法は、Modalにドラッグ機能を追加します.ユーザーは十分大きいと思っています.そうします.ユーザーは少し大きく見たいので、自分で大きくして、それから私はユーザーの選択を記録して、多重化します.
私の『`resize`とMutationObserverでDOMをスケーリングしサイズを記録する』の学友を見たことがあって、
使用するときは、次の点に注意してください.
まず、要素をスケールすると同時に、サブ要素、親要素にも影響します.静的ドキュメント・ストリームでは、ブロック・レベルの要素の幅は、親要素
次に、ドラッグハンドルの表示優先度が低く、サブエレメントが何も埋め込まれていなくても、エレメントに覆われます.すなわち、
実施形態
要するに、この属性をどの要素に加えるかは、こだわりがあります.具体的には、Bootstrap Modalは、
ただし、幅を制限するのは親要素、すなわち
だからウィンドウが完全に展開すると、幅の高さを取得し、 に書き込む.はその後、 である.は、 をグローバルに使用するためにlocalStorageに保存する.
完全なコード表示
わが工場の製品はVueに基づいて開発されたので、論理はVueコンポーネントで実現した.
効果のデモ
Codepenに表示しやすいように、一部修正があります.
https://codepen.io/meathill/p...
コードと解釈
に注意
ブラウザの非同期ロードメカニズムのため、modalが開いてレイアウトが完了した後、高さと幅がコンテンツによって押し開かれて記録が不正になったり、コンテンツが異常に隠されたりする可能性があります.読者自身で何とかして、練習問題にしてください.
まとめ
今回のコンポーネント開発は私の理想的なコンポーネントモデルによく合っています.ブラウザオリジナルメカニズム を活用できるだけ少ないJS に合わせる必要な機能は何でも追加し、大きくなくても である.
MVVMフレームワークの連携により,このようなスキームは容易に実現できる.一方、各プロジェクトには独自の使用シーンがあり、長期にわたって特定のシーンで作業することで、このシーンに適したコンポーネントライブラリを徐々に整理し、プロジェクトの開発効率を向上させることができます.これこそコンポーネント化の正道だと思います.
私のブログに同期:
Bootstrapは現在最も流行しているフロントエンドの基礎フレームワークの一つであるべきだ.アーキテクチャの優位性のため、侵入性が低く、さまざまな方法で他のプロジェクトに統合できます.わが工場の各種製品には,みなその活躍の場がある.
先日、ボスはModal(弾窓)が彼のスクリーンに小さすぎて、5 Kディスプレイを浪費していると愚痴をこぼした.
見てみましたが、Bootstrapのデザインで1200 pxを超えるとXLでも
.modal-lg
の幅が1140 pxに固定されています.実はBootstrapがこのように設計されているのも理にかなっている.人の目がフォーカスして幅が限られているので、弾窓が広すぎると、内容が一目で見えなくなり、よくないからだ.しかし、私の工場の製品では、弾窓が火炎図を見せなければならないので、広くてもメリットがあります.技術案
では、総合的に見ると、最も適切な方法は、Modalにドラッグ機能を追加します.ユーザーは十分大きいと思っています.そうします.ユーザーは少し大きく見たいので、自分で大きくして、それから私はユーザーの選択を記録して、多重化します.
私の『`resize`とMutationObserverでDOMをスケーリングしサイズを記録する』の学友を見たことがあって、
resize
のこのCSSの属性を知っているべきで、それを使ってとても便利な元素にスケーリングの機能を追加することができます.caniuseの普及度を参考に、ほとんどの新バージョンのブラウザがサポートされており、安心して利用できます.使用するときは、次の点に注意してください.
まず、要素をスケールすると同時に、サブ要素、親要素にも影響します.静的ドキュメント・ストリームでは、ブロック・レベルの要素の幅は、親要素
content-box
の100%がデフォルトであり、高さは子要素によって決まるからです.したがって、1つのブロックレベルの要素のスケールでは、親要素(幅を制限する場合)よりも広く、子要素よりも低くすることはできません.次に、ドラッグハンドルの表示優先度が低く、サブエレメントが何も埋め込まれていなくても、エレメントに覆われます.すなわち、
padding
のスケールを追加するには、resize
の要素が必要である.実施形態
要するに、この属性をどの要素に加えるかは、こだわりがあります.具体的には、Bootstrap Modalは、
resize
のプロパティを追加するのに最も適しているのはmodal-content
です.1rem
の内側の余白があるからです.ただし、幅を制限するのは親要素、すなわち
modal-dialog
であり、応答式であり、ディスプレイの幅に応じて最大幅を設定します.max-width
modal-content
の最大幅を変更しないと、予想される効果を達成できません.しかしwidth
に変更することはできません.そうすると、弾窓は弾性を失い、解像度が低いときに表現が悪くなります.だから
max-width
で文章を書きます.それを直接取り除くとmodal-dialog
の幅が100%になり、弾窓効果が失われるので、そうすることもできません.最終的に、私の案は:modal-content
のstyle
modal-dialog
のmax-width
を除去するが、このとき、サブエレメントmodal-content
はすでに定幅されているため、依然としてウィンドウスタイルmodal-content
の幅をMutationObserverでモニタし、完全なコード表示
わが工場の製品はVueに基づいて開発されたので、論理はVueコンポーネントで実現した.
効果のデモ
Codepenに表示しやすいように、一部修正があります.
https://codepen.io/meathill/p...
コードと解釈
.modal.simple-modal(
:style="{display: visibility ? 'block' : 'none'}",
@click="doCloseFromBackdrop",
)
.modal-dialog.modal-dialog-scrollable(
ref="dialog",
:class="dialogClass",
)
.modal-content(ref="content", :)
.modal-header.p-2
slot(name="header")
h4 {{title}}
span.close(v-if="canClose", @click="doClose") ×
.modal-body
slot(name="body")
import debounce from 'lodash/debounce';
const RESIZED_SIZE = 'resized_width_key';
let sharedSize = null;
export default {
props: {
canClose: {
type: Boolean,
default: true,
},
size: {
type: String,
default: null,
validator: function(value) {
return ['sm', 'lg', 'xl'].indexOf(value) !== -1;
},
},
resizable: {
type: Boolean,
default: false,
},
backdrop: {
type: Boolean,
default: true,
},
title: {
type: String,
default: 'Modal title',
},
},
computed: {
dialogClass() {
const classes = [];
if (this.size) {
classes.push(`modal-${this.size}`);
}
if (this.resizable) {
classes.push('modal-dialog-resizable');
}
if (this.resizedSize) {
classes.push('ready');
}
return classes.join(' ');
},
contentStyle() {
if (!this.resizable || !this.resizedSize) {
return null;
}
const {width, height} = this.resizedSize;
return {
width: `${width}px`,
height: `${height}px`,
};
},
},
data() {
return {
visibility: false,
resizedSize: null,
};
},
methods: {
async doOpen() {
this.visibility = true;
this.$emit('open');
if (this.resizable) {
// debounce
const onResize = debounce(this.onEditorResize, 100);
// MutationObserver
const observer = this.observer = new MutationObserver(onResize);
observer.observe(this.$refs.content, {
attributes: true,
});
if (sharedSize) {
this.resizedSize = sharedSize;
}
// , Modal ,
if (!this.resizedSize) {
await this.$nextTick();
// , `clientWidth` ,
// https://weibo.com/1263362863/ImwIOmamC
const width = this.$refs.dialog.clientWidth;
this.resizedSize = {width};
// , computed `max-width`
}
}
},
doClose() {
this.visibility = false;
this.$emit('close');
},
doCloseFromBackdrop({target}) {
if (!this.backdrop || target !== this.$el) {
return;
}
this.doClose();
},
onEditorResize([{target}]) {
const width = target.clientWidth;
const height = target.clientHeight;
if (width < 320 || height < 160) {
return;
}
sharedSize = {width, height};
localStorage.setItem(RESIZED_SIZE, JSON.stringify(sharedSize));
},
},
beforeMount() {
const size = localStorage.getItem(RESIZED_SIZE);
if (size) {
this.resizedSize = JSON.parse(size);
}
},
beforeDestroy() {
if (this.observer) {
this.observer.disconnect();
this.observer = null;
}
},
};
に注意
ブラウザの非同期ロードメカニズムのため、modalが開いてレイアウトが完了した後、高さと幅がコンテンツによって押し開かれて記録が不正になったり、コンテンツが異常に隠されたりする可能性があります.読者自身で何とかして、練習問題にしてください.
まとめ
今回のコンポーネント開発は私の理想的なコンポーネントモデルによく合っています.
MVVMフレームワークの連携により,このようなスキームは容易に実現できる.一方、各プロジェクトには独自の使用シーンがあり、長期にわたって特定のシーンで作業することで、このシーンに適したコンポーネントライブラリを徐々に整理し、プロジェクトの開発効率を向上させることができます.これこそコンポーネント化の正道だと思います.
私のブログに同期: