当前位置: 首页 > news >正文

Vue 组件定义模板,集合v-for生成界面

尝试使用vue生成一个界面,界面上条目都是同样的模板,效果如下:

每个文章界面结构相同,js代码中提供了文章实体的链表,界面加载的时候根据这些实体自动生成对应UI;

类似WPF上的效果:https://blog.csdn.net/qq_59062726/article/details/138268351?fromshare=blogdetail&sharetype=blogdetail&sharerId=138268351&sharerefer=PC&sharesource=qq_59062726&sharefrom=from_link

1.编写数据提供类:blogData.js

// 博客数据模拟
export const generateBlogList = (count = 10) => {const titles = ['Vue3响应式原理深入解析','React Hooks最佳实践','Node.js性能优化指南','前端工程化实战','微前端架构设计','Webpack5新特性解析','TypeScript泛型应用','CSS-in-JS方案比较','前端测试策略','浏览器渲染原理']const authors = ['张三', '李四', '王五', '赵六', '钱七']const tagsPool = ['Vue', 'React', 'JavaScript', 'TypeScript', 'CSS', 'Node.js', '前端', '工程化', '性能优化']return Array.from({ length: count }, (_, index) => {const tagCount = Math.floor(Math.random() * 3) + 2const selectedTags = []for (let i = 0; i < tagCount; i++) {const randomTag = tagsPool[Math.floor(Math.random() * tagsPool.length)]if (!selectedTags.includes(randomTag)) {selectedTags.push(randomTag)}}return {id: index + 1,title: titles[index % titles.length] + ` (${index + 1})`,author: authors[Math.floor(Math.random() * authors.length)],publishDate: new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],summary: `这是第${index + 1}篇博客的摘要,这里包含了博客的主要内容和亮点...`,content: `这是第${index + 1}篇博客的完整内容...`,tags: selectedTags,views: Math.floor(Math.random() * 2000),likes: Math.floor(Math.random() * 150),coverImage: `https://picsum.photos/800/400?random=${index}`}})
}// 导出固定数据
export const blogList = generateBlogList(8)

2.定义单个文章组件模板

BlogCard.vue

<template><article class="blog-card" @click="$emit('view-detail', blog)"><div class="blog-header"><img v-if="blog.coverImage" :src="blog.coverImage" :alt="blog.title" class="cover-image"><h3 class="blog-title">{{ blog.title }}</h3></div><div class="blog-meta"><span class="author"><i class="icon-user"></i>{{ blog.author }}</span><span class="date"><i class="icon-calendar"></i>{{ formatDate(blog.publishDate) }}</span><span class="views"><i class="icon-eye"></i>{{ blog.views }} 浏览</span><span class="likes"><i class="icon-heart"></i>{{ blog.likes }} 点赞</span></div><p class="blog-summary">{{ blog.summary }}</p><div class="blog-tags"><span v-for="tag in blog.tags" :key="tag" class="tag":style="{ backgroundColor: getTagColor(tag) }">{{ tag }}</span></div></article>
</template><script>
export default {name: 'BlogCard',props: {blog: {type: Object,required: true}},methods: {formatDate(dateString) {return new Date(dateString).toLocaleDateString('zh-CN')},getTagColor(tag) {const colors = {'Vue': '#42b883','React': '#61dafb','JavaScript': '#f7df1e','TypeScript': '#3178c6','CSS': '#1572b6','Node.js': '#339933'}return colors[tag] || '#6c757d'}}
}
</script><style scoped>
.blog-card {border: 1px solid #e1e8ed;border-radius: 12px;padding: 20px;margin-bottom: 16px;background: white;cursor: pointer;transition: all 0.3s ease;box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}.blog-card:hover {transform: translateY(-2px);box-shadow: 0 4px 16px rgba(0,0,0,0.15);
}.cover-image {width: 100%;height: 200px;object-fit: cover;border-radius: 8px;margin-bottom: 12px;
}.blog-title {color: #2c3e50;margin: 0 0 12px 0;font-size: 1.25rem;line-height: 1.4;
}.blog-meta {display: flex;flex-wrap: wrap;gap: 16px;margin-bottom: 12px;font-size: 0.875rem;color: #6c757d;
}.blog-meta span {display: flex;align-items: center;gap: 4px;
}.blog-summary {color: #495057;line-height: 1.6;margin-bottom: 16px;display: -webkit-box;-webkit-line-clamp: 3;-webkit-box-orient: vertical;overflow: hidden;
}.blog-tags {display: flex;flex-wrap: wrap;gap: 8px;
}.tag {padding: 4px 8px;border-radius: 4px;color: white;font-size: 0.75rem;font-weight: 500;
}/* 图标样式 */
.icon-user::before { content: '👤 '; }
.icon-calendar::before { content: '📅 '; }
.icon-eye::before { content: '👀 '; }
.icon-heart::before { content: '❤️ '; }
</style>

3.在父容器中使用v-for呈现

<template><div class="front-container"><h2>前端技术文章</h2><div class="blog-list"><BlogCard v-for="blog in blogs" :key="blog.id" :blog="blog"@view-detail="handleViewDetail"/></div></div>
</template><script>
import { blogList } from '../../mock/blogData'
import BlogCard from '@/components/BlogCard.vue'export default {name: 'BlogList',components: {BlogCard},data() {return {blogs: blogList}},methods: {handleViewDetail(blog) {console.log('查看博客详情:', blog)}}
}
</script>

分析:

数据流向:

blogData.js文件提供了blogList属性,在父容器中通过blogs引用了blogList,在父容器的v-for中把blogs中每一个实体又给到了BlogCard.vue的blog属性,完成数据填充。

其中包

http://www.dtcms.com/a/438803.html

相关文章:

  • 花生壳域名可以做网站域名吗新闻资讯网站php源码
  • 【C++】list的使用与模拟实现
  • 企业网站宽度给多少怎么从网站知道谁做的
  • 【深度学习新浪潮】国内主流AI视频生成模型(对标Sora2)技术解析与API代码实战
  • 计算字符串的编辑距离
  • 哪里可以做网站的学影视后期的正规学校
  • Python海象运算符使用指南
  • SDL2 _
  • NO.14数据结构红黑树|树高|转化4阶B树|插入操作|删除操作
  • 学网页设计要多长时间南京seo招聘
  • EPOLLONESHOT事件类型和ET模式有什么区别?
  • “多数派”的智慧:Redis Redlock 分布式锁
  • 国家城乡建设官方网站参与做网站的收获
  • 房地产公司网站建设报价方案建立网站是什么建立的
  • 深圳网站建设公司佰达国内saas软件公司排名
  • P10806 [CEOI 2024] 洒水器 题解
  • 温州十大网络公司排名广州网站建设专业乐云seo
  • 做礼品的网站中航长江建设工程有限公司网站
  • SQL ROUND() 函数详解
  • RK3588 SSH相关方法总结(每次遇到问题更新)
  • 国家基础设施建设网站杨园建设社区网站
  • 3. 是网站建设的重点亿唐网不做网站做品牌原因
  • C# TCP 开发笔记(TcpListener/TcpClient)
  • 成都网络优化公司排行榜网站的优化是什么
  • 山西网站建设多少钱怎么做旅游网站
  • JAVA第八学:继承和多态
  • 网站开发前端指什么太原本地网站搭建公司
  • FastAPI 路径操作依赖项
  • wordpress开发网站美业营销策划公司
  • 《强化学习数学原理》学习笔记5——压缩映射定理的证明