5. 创建一个栅栏布局组件-DeepSeek辅助编程

在deepseek中输入:
创建一个vue组件
组件实现栅栏布局的功能

 

deepseek返回的代码:
Row.vue
<template>
  <div 
    class="grid-row"
    :style="rowStyle"
    :class="rowClass"
  >
    <slot></slot>
  </div>
</template>

<script setup>
import { computed, provide } from 'vue'

const props = defineProps({
  gutter: {
    type: [Number, Array],
    default: 0
  },
  justify: {
    type: String,
    default: 'start',
    validator: v => ['start', 'end', 'center', 'space-around', 'space-between'].includes(v)
  },
  align: {
    type: String,
    default: 'top',
    validator: v => ['top', 'middle', 'bottom'].includes(v)
  },
  wrap: {
    type: Boolean,
    default: true
  }
})

// 提供 gutter 给子组件
provide('gridGutter', computed(() => {
  if (Array.isArray(props.gutter)) {
    return { x: props.gutter[0] || 0, y: props.gutter[1] || 0 }
  }
  return { x: props.gutter, y: props.gutter }
}))

const rowStyle = computed(() => {
  const gutter = props.gutter
  if (Array.isArray(gutter)) {
    return { 
      marginLeft: `-${gutter[0]/2}px`,
      marginRight: `-${gutter[0]/2}px`
    }
  }
  return { 
    marginLeft: `-${gutter/2}px`,
    marginRight: `-${gutter/2}px`
  }
})

const rowClass = computed(() => [
  `justify-${props.justify}`,
  `align-${props.align}`,
  { 'nowrap': !props.wrap }
])
</script>

<style scoped>
.grid-row {
  display: flex;
  flex-wrap: wrap;
  box-sizing: border-box;
}

/* 水平排列方式 */
.justify-start { justify-content: flex-start; }
.justify-end { justify-content: flex-end; }
.justify-center { justify-content: center; }
.justify-space-around { justify-content: space-around; }
.justify-space-between { justify-content: space-between; }

/* 垂直对齐方式 */
.align-top { align-items: flex-start; }
.align-middle { align-items: center; }
.align-bottom { align-items: flex-end; }

.nowrap { flex-wrap: nowrap; }
</style>

 

Col.vue
<template>
  <div 
    class="grid-col"
    :class="colClass"
    :style="colStyle"
  >
    <slot></slot>
  </div>
</template>

<script setup>
import { inject, computed } from 'vue'

const props = defineProps({
  span: {
    type: Number,
    default: 24,
    validator: v => v >= 0 && v <= 24
  },
  offset: {
    type: Number,
    default: 0,
    validator: v => v >= 0 && v <= 24
  },
  xs: [Number, Object],
  sm: [Number, Object],
  md: [Number, Object],
  lg: [Number, Object],
  xl: [Number, Object]
})

const gutter = inject('gridGutter')

// 生成响应式 class
const colClass = computed(() => {
  const classes = []
  const breakpoints = { xs: 'xs', sm: 'sm', md: 'md', lg: 'lg', xl: 'xl' }
  
  Object.keys(breakpoints).forEach(breakpoint => {
    if (props[breakpoint]) {
      if (typeof props[breakpoint] === 'number') {
        classes.push(`col-${breakpoint}-${props[breakpoint]}`)
      } else if (typeof props[breakpoint] === 'object') {
        classes.push(
          `col-${breakpoint}-${props[breakpoint].span}`,
          `offset-${breakpoint}-${props[breakpoint].offset || 0}`
        )
      }
    }
  })
  
  return classes
})

// 计算列样式
const colStyle = computed(() => ({
  paddingLeft: `${gutter.value.x / 2}px`,
  paddingRight: `${gutter.value.x / 2}px`,
  paddingTop: `${gutter.value.y / 2}px`,
  paddingBottom: `${gutter.value.y / 2}px`
}))

// 基础宽度计算
const baseWidth = computed(() => (props.span / 24) * 100 + '%')
const offsetWidth = computed(() => (props.offset / 24) * 100 + '%')
</script>

<style scoped>
.grid-col {
  box-sizing: border-box;
  width: v-bind(baseWidth);
  margin-left: v-bind(offsetWidth);
}

/* 响应式断点 */
@media (max-width: 575px) {
  .col-xs-0 { display: none; }
  @for $i from 1 through 24 {
    .col-xs-#{$i} { width: ($i / 24) * 100%; }
    .offset-xs-#{$i} { margin-left: ($i / 24) * 100%; }
  }
}

@media (min-width: 576px) {
  .col-sm-0 { display: none; }
  @for $i from 1 through 24 {
    .col-sm-#{$i} { width: ($i / 24) * 100%; }
    .offset-sm-#{$i} { margin-left: ($i / 24) * 100%; }
  }
}

@media (min-width: 768px) {
  .col-md-0 { display: none; }
  @for $i from 1 through 24 {
    .col-md-#{$i} { width: ($i / 24) * 100%; }
    .offset-md-#{$i} { margin-left: ($i / 24) * 100%; }
  }
}

@media (min-width: 992px) {
  .col-lg-0 { display: none; }
  @for $i from 1 through 24 {
    .col-lg-#{$i} { width: ($i / 24) * 100%; }
    .offset-lg-#{$i} { margin-left: ($i / 24) * 100%; }
  }
}

@media (min-width: 1200px) {
  .col-xl-0 { display: none; }
  @for $i from 1 through 24 {
    .col-xl-#{$i} { width: ($i / 24) * 100%; }
    .offset-xl-#{$i} { margin-left: ($i / 24) * 100%; }
  }
}
</style>

 

调用的代码
<template>
  <Row :gutter="20">
    <!-- 基础用法 -->
    <Col :span="12"><div class="demo">50% 宽度</div></Col>
    <Col :span="12"><div class="demo">50% 宽度</div></Col>

    <!-- 响应式布局 -->
    <Col :xs="24" :sm="12" :md="8" :lg="6">
      <div class="demo">响应式列</div>
    </Col>

    <!-- 带偏移量 -->
    <Col :span="8" :offset="4">
      <div class="demo">偏移列</div>
    </Col>

    <!-- 混合配置 -->
    <Col :span="6" :md="{ span: 8, offset: 2 }">
      <div class="demo">复杂配置</div>
    </Col>
  </Row>
</template>

<script setup>
import { Row, Col } from '@/components/Grid'
</script>

<style>
.demo {
  background: #f0f2f5;
  height: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>

这里会碰到一个错误

ERROR in ./src/components/Grid/TCol.vue?vue&type=style&index=0&id=be77a196&scoped=true&lang=css (./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/Grid/TCol.vue?vue&type=style&index=0&id=be77a196&scoped=true&lang=css)
Module build failed (from ./node_modules/postcss-loader/dist/cjs.js):
SyntaxError

(12:17) D:\xxx\Demo\my-vue-project\src\components\Grid\TCol.vue Unknown word $i

  10 |     .col-xs-0 { display: none; }
  11 |     @for $i from 1 through 24 {
> 12 |       .col-xs-#{$i} { width: ($i / 24) * 100%; }
     |                 ^
  13 |       .offset-xs-#{$i} { margin-left: ($i / 24) * 100%; }
  14 |     }
 @ ./node_modules/vue-style-loader/index.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/Grid/TCol.vue?vue&type=style&index=0&id=be77a196&scoped=true&lang=css 4:14-360 15:3-20:5 16:22-368
 @ ./src/components/Grid/TCol.vue?vue&type=style&index=0&id=be77a196&scoped=true&lang=css 1:0-424 1:0-424
 @ ./src/components/Grid/TCol.vue 5:0-75
 @ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&setup=true&lang=js 9:0-50 67:6-10
 @ ./src/App.vue?vue&type=script&setup=true&lang=js 1:0-200 1:0-200 1:201-390 1:201-390
 @ ./src/App.vue 2:0-65 3:0-60 3:0-60 6:49-55
 @ ./src/main.js 2:0-28 3:10-13

webpack compiled with 1 error

 

可以继续询问deepseek
报错 D:\xxx\Demo\my-vue-project\src\components\Grid\TCol.vue Unknown word $i 如何解决
deepseek返回:
安装 Sass 预处理器:npm install sass sass-loader --save-dev
替换col.vue的样式
<style lang="scss" scoped>
.grid-col {
  box-sizing: border-box;
  width: v-bind(baseWidth);
  margin-left: v-bind(offsetWidth);
}

/* 响应式断点 */
@mixin generate-col($breakpoint) {
  @for $i from 0 through 24 {
    .col-#{$breakpoint}-#{$i} {
      width: ($i / 24) * 100%;
    }
    .offset-#{$breakpoint}-#{$i} {
      margin-left: ($i / 24) * 100%;
    }
  }
}

@media (max-width: 575px) {
  @include generate-col('xs');
  .col-xs-0 { display: none; }
}

@media (min-width: 576px) {
  @include generate-col('sm');
  .col-sm-0 { display: none; }
}

@media (min-width: 768px) {
  @include generate-col('md');
  .col-md-0 { display: none; }
}

@media (min-width: 992px) {
  @include generate-col('lg');
  .col-lg-0 { display: none; }
}

@media (min-width: 1200px) {
  @include generate-col('xl');
  .col-xl-0 { display: none; }
}
</style>

 

运行之后可以得到结果
0
posted @ 2025-03-17 11:01  Terry841119  阅读(24)  评论(0)    收藏  举报