我正在研究vue.js / nuxt.js项目,应用Atomic Design方法,我需要做一个设置网格布局并使用CSS Grid Layout。
我已经做了组件
GridLayout.vue
<template>
<div class="grid">
<style>
{{ css }}
</style>
<slot />
</div>
</template>
<script>
export default {
props: {
columns: String,
rows: String,
areas: String,
gap: String,
columnGap: String,
rowGap: String,
// breakpoints
small: Object,
medium: Object,
large: Object
},
computed: {
css () {
let large = ''
let finalStyle = ''
// generic
let generic = ''
if (this.columns) generic += `grid-template-columns: ${this.columns};`
if (this.rows) generic += `grid-template-rows: ${this.rows};`
if (this.areas) generic += `grid-template-areas: "${this.areas}";`
if (this.gap) generic += `grid-gap: ${this.gap};`
if (this.columnGap) generic += `grid-column-gap: ${this.columnGap};`
if (this.rowGap) generic += `grid-row-gap: ${this.rowGap};`
finalStyle += ` .grid { ${generic} }`
// small
let small = ''
if (this.small) {
if (this.small.columns) small += `grid-template-columns: ${this.small.columns};`
if (this.small.rows) small += `grid-template-rows: ${this.small.rows};`
if (this.small.areas) small += `grid-template-areas: "${this.small.areas}";`
if (this.small.gap) small += `grid-gap: ${this.small.gap};`
if (this.small.columnGap) small += `grid-column-gap: ${this.small.columnGap};`
if (this.small.rowGap) small += `grid-row-gap: ${this.small.rowGap};`
finalStyle += `@media (max-width: 600px) { .grid { ${small} } } `
}
// medium
let medium = ''
if (this.medium) {
if (this.medium.columns) medium += `grid-template-columns: ${this.medium.columns};`
if (this.medium.rows) medium += `grid-template-rows: ${this.medium.rows};`
if (this.medium.areas) medium += `grid-template-areas: "${this.medium.areas}";`
if (this.medium.gap) medium += `grid-gap: ${this.medium.gap};`
if (this.medium.columnGap) medium += `grid-column-gap: ${this.medium.columnGap};`
if (this.medium.rowGap) medium += `grid-row-gap: ${this.medium.rowGap};`
finalStyle += `@media (min-width: 600px) and (max-width: 992px) { .grid { ${medium} } } `
}
return finalStyle
},
},
}
</script>
<style lang="scss" scoped>
.grid {
display: grid;
}
</style>
在任何页面上使用组件。vue
<template>
<GridLayout
columns="1fr 1fr 1fr 1fr"
rows="auto"
gap="10px"
:medium="{
columns: '1fr 1fr',
rows:'auto auto'
}"
:small="{
columns: '1fr',
rows: 'auto auto auto auto',
}"
>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>3</h1>
</GridLayout>
</template>
<script>
import { GridLayout } from '@/components/bosons'
export default {
components: {
GridLayout
}
}
</script>
<style>
中的样式标签<template>
需要确定范围,仅应用于组件本身child align
)时,都必须在计算的所有位置添加generic
,small
,{{ 1}},medium
我该如何解决这些问题?也许让我的代码更小,更智能,更少重复
预先感谢
答案 0 :(得分:0)
将样式标签放在模板中会产生警告;该警告说明了为什么应避免使用它:
模板仅应负责将状态映射到UI。避免在模板中放置带有副作用的标签,例如
<style>
,因为它们不会被解析。
您有一个SFC(单个文件组件),它已经定义了作用域样式块-将其用于任何预定义样式。对于动态生成的样式,您将必须使用样式绑定,例如:
<div class="grid" :style="css">
<slot />
</div>
...
computed: {
css () {
let generic = {}
if (this.columns) generic['grid-template-columns'] = this.columns;
if (this.columns) generic['grid-template-rows'] = this.rows;
...
return [generic, large, mediumn, small];
您可以在以下https://vuejs.org/v2/guide/class-and-style.html#Binding-Inline-Styles的Vue文档中了解有关此内容的更多信息。
您还可以查看vue-styled-components
:https://github.com/styled-components/vue-styled-components。我只将它用于React,但我认为它对在Vue中使用情况同样有用。
将重复的代码提取到一个函数中,并根据需要多次调用该代码。这称为制作代码DRY。例如:
methods: {
generateGridStyles(options) {
return {
'grid-template-columns': options.columns || this.columns,
'grid-template-rows': options.rows || this.rows,
'grid-template-areas': options.areas || this.areas,
'grid-gap': options.gap || this.gap,
'grid-column-gap': options.columnGap || this.columnGap,
'grid-row-gap': options.rowGap || this.rowGap,
}
}
}
以下是该功能的使用方式:
let small;
if (this.small) {
small = generateGridStyles(this.small);
}
抽象是有开销的:另一个要维护和推理的组件。考虑一下您的总体设计以及GridLayout
组件的目标是什么。
在我看来,CSS网格布局已经相当简单了,您的组件似乎只是通过CSS网格属性并将它们映射到包装器中。它并没有抽象出使用CSS网格的任何工作。当更容易维护和阅读“原始” CSS网格样式并使用媒体查询来调整样式时,我看不到这样做的好处。