flexbox/src/App.vue

523 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import {ref, watch, onMounted, reactive} from "vue";
/** 子项默认宽度 */
const itemWidth = ref(10);
/** 父Flex属性Flex容器 默认值 */
const flexContainerForm: { [key: string]: any } = reactive({
"flex-direction": "row",
"flex-wrap": "nowrap",
"justify-content": "flex-start",
"align-items": "stretch",
"align-content": "stretch",
});
/** 选项值,默认值 */
const flexContainerList = {
"flex-direction": {
title: "flex-direction",
list: ["row", "row-reverse", "column", "column-reverse"],
modelValue: "row",
},
"flex-wrap": {
title: "flex-wrap",
list: ["nowrap", "wrap", "wrap-reverse"],
modelValue: "nowrap",
},
"justify-content": {
title: "justify-content",
list: ["flex-start", "flex-end", "center", "space-between", "space-around"],
modelValue: "flex-start",
},
"align-items": {
title: "align-items",
list: ["stretch", "flex-start", "flex-end", "center", "baseline"],
modelValue: "stretch",
},
"align-content": {
title: "align-content",
list: [
"stretch",
"flex-start",
"flex-end",
"center",
"space-between",
"space-around",
],
modelValue: "stretch",
},
};
/** 子项初始个数 */
const itemCount = 5;
/** 当前子项总数 */
let itemListCount = ref(itemCount);
/** 子项-单项默认值 */
const itemFormDefaultValue: { [key: string]: number | string } = {
order: 0,
"flex-grow": 0,
"flex-shrink": 1,
"flex-basis": "auto",
"align-self": "auto",
};
/** align-self 选项 */
const itemAlignSelf = [
"auto",
"stretch",
"center",
"flex-start",
"flex-end",
"baseline",
];
/** 子项列表 JSON 数据 */
let flexItemForm: {
[key: string]: any;
} = reactive({});
/** 增加子项 */
const addItem = () => {
itemListCount.value++;
flexItemForm[`item-` + itemListCount.value] = JSON.parse(
JSON.stringify(itemFormDefaultValue)
);
};
/** 减少子项 */
const removeItem = (key: string | number) => {
delete flexItemForm[key];
delete flexItemFormStyle[key];
};
/** 横杆后的字母变大写 */
const toUp = (str: string) => {
let newStr = "";
let arr = str.split("-"); //先用字符串分割成数组
arr.forEach((item, index) => {
if (index > 0) {
return (newStr += item.replace(item[0], item[0].toUpperCase()));
} else {
return (newStr += item);
}
});
return newStr;
};
/** flexBox style */
let flexContainerFormStyle: { [key: string]: any } = reactive({});
const flexContainerFormStyleFun = () => {
Object.keys(flexContainerForm).forEach((key) => {
flexContainerFormStyle["display"] = "flex";
flexContainerFormStyle["height"] = "95%";
flexContainerFormStyle[toUp(key)] = flexContainerForm[key];
});
};
/** flexContainerForm 父属性 默认值监听*/
watch(flexContainerForm, () => {
// flexContainerFormStyle = {};
flexContainerFormStyleFun();
});
/** 子项 style 生成 */
let flexItemFormStyle: { [key: string]: any } = reactive({});
const flexItemFormStyleFun = () => {
Object.keys(flexItemForm).forEach((ikey) => {
let valueObj: any = {};
let flexItemFormIkey = flexItemForm[ikey];
Object.keys(flexItemFormIkey).forEach((_ikeys) => {
// valueObj['backgroundColor'] = 'cornsilk';
valueObj["width"] = itemWidth.value + "%";
// valueObj['minHeight'] = '80px';
// valueObj['display'] = 'inline-block';
valueObj[toUp(_ikeys)] = flexItemFormIkey[_ikeys];
});
flexItemFormStyle[ikey] = valueObj;
});
};
/** 监听子项 和 宽度样式变化 */
watch([flexItemForm, itemWidth], () => {
// flexItemFormStyle = {};
flexItemFormStyleFun();
});
/** 初始 子项 默认值 */
const initialFlexItemForm = () => {
for (let index = 0; index < itemCount; index++) {
flexItemForm[`item-` + index] = JSON.parse(
JSON.stringify(itemFormDefaultValue)
);
}
}
/**
* 准备html和css 打印准备
*/
/** 盒子dom */
let fiexBoxDom: any = ref(null);
/** 要输出的html */
let fiexBoxDomHtml: any = ref(``);
/** 外层 CSS */
let fiexBoxCssString: any = ref(``);
/** 子项 CSS */
let fiexItemCssString: any = ref(``);
/** 生成HTML方法 */
const fiexSubmitHtml = () => {
let html = `<div class="flexbox">`;
// 获取所有子项
Object.keys(flexItemForm).forEach((ikey, index) => {
const itemClass = "flex-item item-" + (index + 1);
html += `<div class="${itemClass}">${itemClass}</div>`;
});
html += `</div>`;
fiexBoxDomHtml.value = html;
};
/** 生成CSS方法{} */
const fiexSubmitCss = () => {
/** 增加CSS外层{} */
const addKuohao = (css: string) => {
return `{` + css + `}`;
};
const flexboxitemDom = fiexBoxDom.value.querySelectorAll(".flexboxitem");
let css: string = ".flex-item{display: inline-block; min-height: 80px; background-color: cornsilk; margin: 5px; overflow: hidden;}";
flexboxitemDom.forEach((dom: any, index: string) => {
css += `.item-` + (index + 1) + addKuohao(dom.style.cssText);
});
fiexBoxCssString.value = `.flexbox{` + fiexBoxDom.value.style.cssText + `}`;
fiexItemCssString.value = css;
};
/** 获取打印html和css */
const fiexSubmit = () => {
fiexSubmitHtml();
fiexSubmitCss();
};
/** 初始页面加载后只执行一次 */
onMounted(() => {
initialFlexItemForm();
flexContainerFormStyleFun();
flexItemFormStyleFun();
});
/**
* 底部
*/
const showTime: any = ref('');
const showTimeYear: any = ref(0);
const checkTime = function (i: any) {
if (i < 10) {
i = "0" + i;
}
return i;
};
const showTimeFun = function () {
const nowdate = new Date();
let year = nowdate.getFullYear(),
month = nowdate.getMonth() + 1,
date = nowdate.getDate(),
day = nowdate.getDay(),
week = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
h: string | number = nowdate.getHours(),
m: string | number = nowdate.getMinutes(),
s: string | number = nowdate.getSeconds();
h = checkTime(h);
m = checkTime(m);
s = checkTime(s);
// 年
showTimeYear.value = year.toString();
// 日期时间
showTime.value = year + "年" + month + "月" + date + "日" + week[day] + " " + h + ":" + m + ":" + s;
};
showTimeFun();
setInterval(() => {
showTimeFun();
}, 1000); //反复执行函数
</script>
<template>
<div class="layout">
<a-layout>
<a-layout-header>
<h1><strong>CSS3 Flexbox 在线演示</strong></h1>
</a-layout-header>
<a-layout-content>
<a-row class="flexrow">
<a-col class="arcocol">
<h3>子项宽度</h3>
<div>
<span>Width{{ itemWidth }}</span>
<a-slider
v-model="itemWidth"
:min="10"
:max="100"
:step="1"
:style="{ paddingLeft: '10px', width: '90%' }"
/>
</div>
<a-divider :margin="20" :size="2">
<icon-heart/>
</a-divider>
<h3>父Flex属性Flex容器</h3>
<div>
<a-form :model="flexContainerForm">
<a-row class="flexcontainer">
<a-col
class="acol"
v-for="(item, key) in flexContainerList"
:key="key"
>
<h4>
<strong>{{ item.title }}</strong>
</h4>
<a-radio-group
direction="vertical"
v-model="flexContainerForm[key]"
>
<a-radio
v-for="(value, keys) in item.list"
:value="value"
:key="keys"
>
{{ value }}
</a-radio>
</a-radio-group>
</a-col>
</a-row>
<a-button
@click="fiexSubmit"
:style="{ marginTop: '15px' }"
type="primary"
status="success">
获取
</a-button>
<a-alert
type="success"
:show-icon="false"
:style="{ padding: '20px', marginTop: '15px' }"
v-if="fiexBoxDomHtml || fiexBoxCssString || fiexItemCssString"
>
<a-alert type="error" :show-icon="false">{{ fiexBoxDomHtml }}</a-alert>
<a-divider/>
{{ fiexBoxCssString }}
<a-divider/>
{{ fiexItemCssString }}
<a-divider/>
</a-alert>
</a-form>
</div>
</a-col>
<a-col class="arcocol" :style="{ padding: '20px 5px' }">
<h3>
实现效果
<a-button
type="primary"
@click="addItem"
:style="{ float: 'right' }"
>
<template #icon>
<icon-plus/>
</template>
新增子项
</a-button>
</h3>
<div :style="{ height: '100%' }">
<div
class="flexbox"
:style="flexContainerFormStyle"
ref="fiexBoxDom"
>
<div
class="flexboxitem"
v-for="(_, indexKey, index) in flexItemForm"
:key="index"
:style="flexItemFormStyle[indexKey]"
>
<a-card :title="(index + 1).toString()" :bordered="false">
<template #extra>
<a-button
type="text"
shape="circle"
@click="removeItem(indexKey)"
>
<icon-close/>
</a-button>
</template>
<a-list>
<a-list-item>
<a-tooltip content="order">
<a-input-number
v-model="flexItemForm[indexKey].order"
:min="0"
model-event="input"
/>
</a-tooltip>
</a-list-item>
<a-list-item>
<a-tooltip content="flex-grow">
<a-input-number
v-model="flexItemForm[indexKey]['flex-grow']"
:min="0"
model-event="input"
/>
</a-tooltip>
</a-list-item>
<a-list-item>
<a-tooltip content="flex-shrink">
<a-input-number
v-model="flexItemForm[indexKey]['flex-shrink']"
:min="1"
:max="100"
model-event="input"
/>
</a-tooltip>
</a-list-item>
<a-list-item>
<a-tooltip content="flex-basis">
<a-input
v-model="flexItemForm[indexKey]['flex-basis']"
allow-clear
/>
</a-tooltip>
</a-list-item>
<a-list-item>
<a-tooltip content="align-self">
<a-select
v-model="flexItemForm[indexKey]['align-self']"
>
<a-option
v-for="ikeys in itemAlignSelf"
:key="ikeys"
>
{{ ikeys }}
</a-option>
</a-select>
</a-tooltip>
</a-list-item>
</a-list>
</a-card>
</div>
</div>
</div>
</a-col>
</a-row>
</a-layout-content>
<a-layout-footer ref="showTimeDom">
<a-row class="footer" :gutter="24">
<a-col :span="12">
<div>{{ showTime }}</div>
</a-col>
<a-col :span="12">
<span :style="{padding:'0 10px'}">Copyright © 2015-{{ showTimeYear }}</span>
<a target="_blank" rel="noopener" href="https://beian.miit.gov.cn/"> 鲁ICP备10001546号 </a>
</a-col>
</a-row>
</a-layout-footer>
</a-layout>
</div>
</template>
<style scoped>
h3 {
font-weight: 700;
padding-bottom: 15px;
}
/**
效果实现
*/
.flexbox {
padding: 10px;
background-color: goldenrod;
}
.flexbox :deep(.arco-card-size-medium .arco-card-body) {
padding: 5px;
}
.flexbox :deep(.arco-list-bordered) {
border: none;
}
.flexbox :deep(.arco-input-wrapper),
.flexbox :deep(.arco-select-view-single) {
background-color: transparent;
}
.flexboxitem {
min-height: 80px;
background-color: cornsilk;
display: inline-block;
margin: 5px;
overflow: hidden;
}
.flexboxitem :deep(.arco-card) {
background: transparent;
}
.flexboxitem :deep(.arco-list-wrapper),
.flexboxitem :deep(.arco-list-medium .arco-list-content-wrapper .arco-list-content > .arco-list-item) {
padding: 0;
}
.layout,
.layout :deep(.arco-layout) {
height: 100%;
}
.layout :deep(.arco-layout-header),
.layout :deep(.arco-layout-footer),
.layout :deep(.arco-layout-content) {
display: flex;
flex-direction: column;
justify-content: center;
/*color: var(--color-white);*/
font-size: 16px;
font-stretch: condensed;
text-align: center;
}
.layout :deep(.arco-layout-header),
.layout :deep(.arco-layout-footer) {
height: 64px;
background-color: #00bd7e;
}
.layout :deep(.arco-layout-footer) {
background-color: transparent;
}
.layout :deep(.arco-layout-content) {
/*background-color: goldenrod;*/
}
.flexrow,
.flexcontainer {
/*color: var(--color-white);*/
align-items: stretch;
height: 100%;
text-align: left;
}
.flexrow .arcocol {
flex: 1 1 50%;
padding: 20px;
color: #181818;
}
.flexcontainer .acol {
flex: 1 0 20%;
/*flex-basis: 0;*/
}
.footer {
color: hsla(160, 100%, 37%, 1);
}
</style>