最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.13

IT圈 admin 1浏览 0评论

【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.13

【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.13-3.15)

本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会

持续更新中…

3.13 web页新闻资讯的数据接口

// server\models\Category.js
// 优化完善分类模型,建立虚拟联接
const mongoose = require('mongoose')// 定义模型字段
const schema = new mongoose.Schema({name: {type: String,required: true},parent: { type: mongoose.SchemaTypes.ObjectId, ref: 'Category' } // 类型为ObjectId 并关联Category表
})// 3.13 设置虚拟字段:子分类,类似vue中的计算属性,它是通过已定义的schema属性的计算\组合\拼接得到的新的值
schema.virtual('children', {localField: '_id', // 内键,schema对应的模型Title的_idforeignField: 'parent', //外键,关联模型Category的parent键justOne: false, // 只查询一条数据ref: 'Category' // 关联的模型
})// 3.13 分类关联新闻标题
schema.virtual('newsList', {localField: '_id', // 内键,schema对应的模型Category的_idforeignField: 'categories', //外键,关联模型Article的categories键justOne: false, // 只查询一条数据ref: 'Article' // 关联的模型
})// 导出Category模型,哪里需要用,哪里引入,引入到 routes/admin/index.js
module.exports = mongoose.model('Category', schema)
    // server\routes\web\index.js// 新增 新闻列表接口,用于前端调用。以分类为主题,关联新闻router.get('/news/list', async (req, res) => {// //3.13 调出子分类,顺便调出子分类里的新闻,用populate关联,用lean展示出来,但存在问题不能查询单独的分类数量// const parent = await Category.findOne({//     name: '新闻资讯'// }).populate({//     path: 'children',//     populate: {//         path: 'newsList'//     }// }).lean()// 3.13 另一种方式,聚合查询,可以同时查询多次,聚合参数叫聚合管道const parent = await Category.findOne({name: '新闻资讯'})const cats = await Category.aggregate([// 条件查询:字段 = 上级分类,找到分类,这一步与where查询没有太大区别{ $match: { parent: parent._id } },// 类似与关系数据库的关联联接,左关联联接left join// 定义模型是,第三个参数collection省略了,它表示集合的名字,省略后默认是模型的复数小写。// 从哪个集合,本地键,外键、as给起个名字{ $lookup: { from: 'articles', localField: '_id', foreignField: 'categories', as: 'newsList' } },// 定义要几个.添加\修改字段,特殊操作符slice //  每一个分类只要5个{ $addFields: { newsList: { $slice: ['$newsList', 5] } } }])const subCats = cats.map(v => v._id)// 热门分类,是独立于四个分类,新增的,不限制分类,条件是 子分类是那些 in操作符会筛选出字段值等于制定数组中任何值的文档cats.unshift({name: '热门',newsList: await Artice.find().where({categories: { $in: subCats }// 关联 categories字段,把_id拓展为名称}).populate('categories').limit(5).lean()})// 把newsList上增加catergoryName,方便前端显示cats.map(cat => {cat.newsList.map(news => {news.categoryName = cat.name === '热门' ? news.categories[0].name : cat.namereturn news})return cat})res.send(cats)})

3.14 web页首页新闻资讯界面展示

前端安装 axios 配置http.js 偷个懒,和admin一致,注意的是请求地址为

 baseURL: 'http://localhost:3000/web/api'
// web端安装日期时间格式化工具
npm install dayjs --save
// 单行文字,多余的省略掉
// text overflow
.text-ellipsis {display: inline-block;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}

完整代码如下

// web\src\views\Home.vue
<template><div class="home"><swiper ref="mySwiper" :options="swiperOptions"><swiper-slide><imgclass="w-100"src="../assets/images/201.jpeg"alt=""sizes=""srcset=""/></swiper-slide><swiper-slide><imgclass="w-100"src="../assets/images/202.jpeg"alt=""sizes=""srcset=""/></swiper-slide><swiper-slide><imgclass="w-100"src="../assets/images/203.jpeg"alt=""sizes=""srcset=""/></swiper-slide><swiper-slide><imgclass="w-100"src="../assets/images/204.jpeg"alt=""sizes=""srcset=""/></swiper-slide><divclass="swiper-pagination pagination-home text-right px-3 pb-2"slot="pagination"></div></swiper><!-- end of swiper --><!-- 图标导航 --><!-- 外部容器text-center pt-3 内部容易mb-3 这样能统一样式 --><transition name="fade" mode="out-in"><divclass="nav-icons bg-white mt-3 d-flex flex-wrap text-center pt-3 text-grey-1"><!-- <div class="nav-icons bg-white mt-3 text-center pt-3 text-grey-1"> --><!-- <div class="nav-item mb-3" v-for="n in 10" :key="n"><i class="sprite sprite-news"></i><div class="py-2">爆料站</div></div> --><!-- 处理底部的收起按钮,需要把d-flex flex-wrap 放在子集的div上,跟它平级写个收起的div --><div class="d-flex flex-wrap" :class="{ toggleActive: isCollapse }"><a href class="nav-item my-3"><i class="sprite sprite-news"></i><div>爆料站</div></a><a href class="nav-item my-3"><i class="sprite sprite-practice"></i><div>故事站</div></a><a href class="nav-item my-3"><i class="sprite sprite-affair"></i><div>周边商城</div></a><a href class="nav-item my-3 border-none"><i class="sprite sprite-mall"></i><div>体验服</div></a><a href class="nav-item my-2"><i class="sprite sprite-start"></i><div>新人专区</div></a><a href class="nav-item my-2"><i class="sprite sprite-honour"></i><div>荣耀·传承</div></a><a href class="nav-item my-2"><i class="sprite sprite-community"></i><div>同人社区</div></a><a href class="nav-item my-2 border-none"><i class="sprite sprite-base"></i><div>王者营地</div></a><a href class="nav-item my-2"><i class="sprite sprite-echart"></i><div>公众号</div></a><a href class="nav-item my-2"><i class="sprite sprite-edition"></i><div>版本介绍</div></a></div><!-- <div class="d-flex flex-wrap"> --><divclass="bg-light py-2 fs-sm;"style="width: 100%"@click="switchActive"><iclass="sprite sprite-arrow mr-1":style="{ transform: isCollapse ? 'rotate(180deg)' : '' }"></i><span class="retract">{{ isCollapse ? '收起' : '展开' }}</span></div></div></transition><!-- end of 图标模块 --><!-- begin of 字体图标 --><!-- <i class="iconfont icon-news text-primary"></i> --><!-- end of 字体图标 --><!-- begin of 新闻资讯卡片 --><div class="card mt-3 p-3 bg-white"><div class="card-header d-flex ai-center pb-3"><i class="iconfont icon-caidananniudianji" style="color: deeppink"></i><div class="fs-xl flex-1 px-2">新闻资讯</div><i class="iconfont icon-menu"></i></div><div class="card-body pt-3"><div class="nav jc-between"><div class="nav-item active"><div class="nav-link">热门</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div></div><div class="pt-3"><swiper><swiper-slide v-for="m in 5" :key="m"><div class="py-2" v-for="n in 5" :key="n"><span>[新闻]</span><span>|</span><span>春和景明柳垂莺娇,峡谷好礼随春报到</span><span>06/12</span></div></swiper-slide></swiper></div></div></div><a-card icon="caidananniudianji" title="新闻资讯-全局组件"><!-- 应用插槽展示数据 --><div class="nav jc-between"><div class="nav-item active"><div class="nav-link">热门</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div></div><div class="pt-3"><swiper><swiper-slide v-for="m in 5" :key="m"><div class="py-2" v-for="n in 5" :key="n"><span>[新闻]</span><span>|</span><span>春和景明柳垂莺娇,峡谷好礼随春报到</span><span>06/12</span></div></swiper-slide></swiper></div></a-card><!-- 封装好的高级组件 --><m-list-cardicon="caidananniudianji"title="新闻资讯-ListCard组件":categories="newsCats"><!-- 在父组件里,不通过循环,直接拿到子组件里的具名slot的数据,这样的好处是 子组件的内容可以由父组件决定怎么展示 --><template #items="{ category }"><divclass="py-2 fs-lg d-flex"v-for="(item, index) in category.newsList":key="index"><span class="text-info" v-text="`[${item.categoryName}]`">[新闻]</span><span class="px-1">|</span><spanclass="flex-1 text-dark-1 text-ellipsis pr-2"v-text="item.title">春和景明柳垂莺娇,峡谷好礼随春报到</span><span class="text-grey-1 fs-sm">{{ item.createdAt | date }}</span></div></template><!-- <template v-slot:heros="{ category }"></template> --></m-list-card><m-card icon="caidananniudianji" title="新闻资讯-局部组件"></m-card><m-card icon="caidananniudianji" title="英雄列表"></m-card><m-card icon="caidananniudianji" title="精彩视频"></m-card><m-card icon="caidananniudianji" title="图文攻略"></m-card><!-- end of 新闻资讯卡片 --></div>
</template><script>import dayjs from 'dayjs';// @ is an alias to /srcimport Card from '../components/Card';export default {filters: {date(val) {return dayjs(val).format('MM/DD');},},name: 'Home',components: { 'm-card': Card },data() {return {swiperOptions: {slidesPerView: 1,autoplay: {disableOnInteraction: false,delay: 2000,},pagination: {el: '.swiper-pagination',clickable: true,},},isCollapse: true,// 定义ListCard组件的数据结构// newsList的简单写法,新建数组5填充1,再map循环替换成对象newsCats: [{_id: 1,name: '热门',newsList: new Array(5).fill(1).map((v) => ({_id: v + 201,categoryName: '赛事',title: '景明柳垂莺娇,峡谷好礼随春报到',date: '06/01',})),},{_id: 2,name: '新闻',newsList: new Array(5).fill(2).map((v) => ({_id: v + 202,categoryName: '赛事',title: '景明柳垂莺娇,峡谷好礼随春报到',date: '06/01',})),},],// 后台数据// newsCats: [],herosCats: [],};},created() {this.fetchNewsCats();},mounted() {console.log('Current Swiper instance object', this.swiper);//   this.swiper.slideTo(3, 1000, false);},computed: {swiper() {return this.$refs.mySwiper.$swiper;},},methods: {async fetchNewsCats() {const res = await this.$http.get('news/list');this.newsCats = res.data;},switchActive() {this.isCollapse = !this.isCollapse;},},};
</script>
<style lang='scss' scope>@import '../style/variables.scss';//  重新定义一个class,便于单独管理各个页面的swipers.pagination-home {.swiper-pagination-bullet {display: inline-block;opacity: 1;border-radius: 0.1538rem;background-color: map-get($colors, 'white');//   background-color: #ffffff;&.swiper-pagination-bullet-active {background: map-get($colors, 'info');}}}.nav-icons {border-top: 1px solid $border-color;border-bottom: 1px solid $border-color;.nav-item {width: 25%;// 取消右侧的边框border-right: 1px solid $border-color;&:nth-child(4n) {border-right: none;}}}.toggleActive {height: 60px;overflow: hidden;}.fade-enter {opacity: 0;}.fade-leave {opacity: 1;}.fade-leave-active,.fade-enter-active {transition: opacity 0.9s;}
</style>

3.15 web首页英雄列表提取官方数据

// 简化版
$$('.hero-nav > li').map(( li,i)=>{return {heros:$$('li',$$('.hero-list')[i]).map(el=>{return {name:$$('h3',el)[0].innerHTML}}),name:li.innerText}})
// 获取img链接,并转成json数据
JSON.stringify($$('.hero-nav > li').map(( li,i)=>{return {heros:$$('li',$$('.hero-list')[i]).map(el=>{return {name:$$('h3',el)[0].innerHTML,avatar:$$('img',el)[0].src}}),name:li.innerText}}))

【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.13

【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.13-3.15)

本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会

持续更新中…

3.13 web页新闻资讯的数据接口

// server\models\Category.js
// 优化完善分类模型,建立虚拟联接
const mongoose = require('mongoose')// 定义模型字段
const schema = new mongoose.Schema({name: {type: String,required: true},parent: { type: mongoose.SchemaTypes.ObjectId, ref: 'Category' } // 类型为ObjectId 并关联Category表
})// 3.13 设置虚拟字段:子分类,类似vue中的计算属性,它是通过已定义的schema属性的计算\组合\拼接得到的新的值
schema.virtual('children', {localField: '_id', // 内键,schema对应的模型Title的_idforeignField: 'parent', //外键,关联模型Category的parent键justOne: false, // 只查询一条数据ref: 'Category' // 关联的模型
})// 3.13 分类关联新闻标题
schema.virtual('newsList', {localField: '_id', // 内键,schema对应的模型Category的_idforeignField: 'categories', //外键,关联模型Article的categories键justOne: false, // 只查询一条数据ref: 'Article' // 关联的模型
})// 导出Category模型,哪里需要用,哪里引入,引入到 routes/admin/index.js
module.exports = mongoose.model('Category', schema)
    // server\routes\web\index.js// 新增 新闻列表接口,用于前端调用。以分类为主题,关联新闻router.get('/news/list', async (req, res) => {// //3.13 调出子分类,顺便调出子分类里的新闻,用populate关联,用lean展示出来,但存在问题不能查询单独的分类数量// const parent = await Category.findOne({//     name: '新闻资讯'// }).populate({//     path: 'children',//     populate: {//         path: 'newsList'//     }// }).lean()// 3.13 另一种方式,聚合查询,可以同时查询多次,聚合参数叫聚合管道const parent = await Category.findOne({name: '新闻资讯'})const cats = await Category.aggregate([// 条件查询:字段 = 上级分类,找到分类,这一步与where查询没有太大区别{ $match: { parent: parent._id } },// 类似与关系数据库的关联联接,左关联联接left join// 定义模型是,第三个参数collection省略了,它表示集合的名字,省略后默认是模型的复数小写。// 从哪个集合,本地键,外键、as给起个名字{ $lookup: { from: 'articles', localField: '_id', foreignField: 'categories', as: 'newsList' } },// 定义要几个.添加\修改字段,特殊操作符slice //  每一个分类只要5个{ $addFields: { newsList: { $slice: ['$newsList', 5] } } }])const subCats = cats.map(v => v._id)// 热门分类,是独立于四个分类,新增的,不限制分类,条件是 子分类是那些 in操作符会筛选出字段值等于制定数组中任何值的文档cats.unshift({name: '热门',newsList: await Artice.find().where({categories: { $in: subCats }// 关联 categories字段,把_id拓展为名称}).populate('categories').limit(5).lean()})// 把newsList上增加catergoryName,方便前端显示cats.map(cat => {cat.newsList.map(news => {news.categoryName = cat.name === '热门' ? news.categories[0].name : cat.namereturn news})return cat})res.send(cats)})

3.14 web页首页新闻资讯界面展示

前端安装 axios 配置http.js 偷个懒,和admin一致,注意的是请求地址为

 baseURL: 'http://localhost:3000/web/api'
// web端安装日期时间格式化工具
npm install dayjs --save
// 单行文字,多余的省略掉
// text overflow
.text-ellipsis {display: inline-block;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}

完整代码如下

// web\src\views\Home.vue
<template><div class="home"><swiper ref="mySwiper" :options="swiperOptions"><swiper-slide><imgclass="w-100"src="../assets/images/201.jpeg"alt=""sizes=""srcset=""/></swiper-slide><swiper-slide><imgclass="w-100"src="../assets/images/202.jpeg"alt=""sizes=""srcset=""/></swiper-slide><swiper-slide><imgclass="w-100"src="../assets/images/203.jpeg"alt=""sizes=""srcset=""/></swiper-slide><swiper-slide><imgclass="w-100"src="../assets/images/204.jpeg"alt=""sizes=""srcset=""/></swiper-slide><divclass="swiper-pagination pagination-home text-right px-3 pb-2"slot="pagination"></div></swiper><!-- end of swiper --><!-- 图标导航 --><!-- 外部容器text-center pt-3 内部容易mb-3 这样能统一样式 --><transition name="fade" mode="out-in"><divclass="nav-icons bg-white mt-3 d-flex flex-wrap text-center pt-3 text-grey-1"><!-- <div class="nav-icons bg-white mt-3 text-center pt-3 text-grey-1"> --><!-- <div class="nav-item mb-3" v-for="n in 10" :key="n"><i class="sprite sprite-news"></i><div class="py-2">爆料站</div></div> --><!-- 处理底部的收起按钮,需要把d-flex flex-wrap 放在子集的div上,跟它平级写个收起的div --><div class="d-flex flex-wrap" :class="{ toggleActive: isCollapse }"><a href class="nav-item my-3"><i class="sprite sprite-news"></i><div>爆料站</div></a><a href class="nav-item my-3"><i class="sprite sprite-practice"></i><div>故事站</div></a><a href class="nav-item my-3"><i class="sprite sprite-affair"></i><div>周边商城</div></a><a href class="nav-item my-3 border-none"><i class="sprite sprite-mall"></i><div>体验服</div></a><a href class="nav-item my-2"><i class="sprite sprite-start"></i><div>新人专区</div></a><a href class="nav-item my-2"><i class="sprite sprite-honour"></i><div>荣耀·传承</div></a><a href class="nav-item my-2"><i class="sprite sprite-community"></i><div>同人社区</div></a><a href class="nav-item my-2 border-none"><i class="sprite sprite-base"></i><div>王者营地</div></a><a href class="nav-item my-2"><i class="sprite sprite-echart"></i><div>公众号</div></a><a href class="nav-item my-2"><i class="sprite sprite-edition"></i><div>版本介绍</div></a></div><!-- <div class="d-flex flex-wrap"> --><divclass="bg-light py-2 fs-sm;"style="width: 100%"@click="switchActive"><iclass="sprite sprite-arrow mr-1":style="{ transform: isCollapse ? 'rotate(180deg)' : '' }"></i><span class="retract">{{ isCollapse ? '收起' : '展开' }}</span></div></div></transition><!-- end of 图标模块 --><!-- begin of 字体图标 --><!-- <i class="iconfont icon-news text-primary"></i> --><!-- end of 字体图标 --><!-- begin of 新闻资讯卡片 --><div class="card mt-3 p-3 bg-white"><div class="card-header d-flex ai-center pb-3"><i class="iconfont icon-caidananniudianji" style="color: deeppink"></i><div class="fs-xl flex-1 px-2">新闻资讯</div><i class="iconfont icon-menu"></i></div><div class="card-body pt-3"><div class="nav jc-between"><div class="nav-item active"><div class="nav-link">热门</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div></div><div class="pt-3"><swiper><swiper-slide v-for="m in 5" :key="m"><div class="py-2" v-for="n in 5" :key="n"><span>[新闻]</span><span>|</span><span>春和景明柳垂莺娇,峡谷好礼随春报到</span><span>06/12</span></div></swiper-slide></swiper></div></div></div><a-card icon="caidananniudianji" title="新闻资讯-全局组件"><!-- 应用插槽展示数据 --><div class="nav jc-between"><div class="nav-item active"><div class="nav-link">热门</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div><div class="nav-item"><div class="nav-link">新闻</div></div></div><div class="pt-3"><swiper><swiper-slide v-for="m in 5" :key="m"><div class="py-2" v-for="n in 5" :key="n"><span>[新闻]</span><span>|</span><span>春和景明柳垂莺娇,峡谷好礼随春报到</span><span>06/12</span></div></swiper-slide></swiper></div></a-card><!-- 封装好的高级组件 --><m-list-cardicon="caidananniudianji"title="新闻资讯-ListCard组件":categories="newsCats"><!-- 在父组件里,不通过循环,直接拿到子组件里的具名slot的数据,这样的好处是 子组件的内容可以由父组件决定怎么展示 --><template #items="{ category }"><divclass="py-2 fs-lg d-flex"v-for="(item, index) in category.newsList":key="index"><span class="text-info" v-text="`[${item.categoryName}]`">[新闻]</span><span class="px-1">|</span><spanclass="flex-1 text-dark-1 text-ellipsis pr-2"v-text="item.title">春和景明柳垂莺娇,峡谷好礼随春报到</span><span class="text-grey-1 fs-sm">{{ item.createdAt | date }}</span></div></template><!-- <template v-slot:heros="{ category }"></template> --></m-list-card><m-card icon="caidananniudianji" title="新闻资讯-局部组件"></m-card><m-card icon="caidananniudianji" title="英雄列表"></m-card><m-card icon="caidananniudianji" title="精彩视频"></m-card><m-card icon="caidananniudianji" title="图文攻略"></m-card><!-- end of 新闻资讯卡片 --></div>
</template><script>import dayjs from 'dayjs';// @ is an alias to /srcimport Card from '../components/Card';export default {filters: {date(val) {return dayjs(val).format('MM/DD');},},name: 'Home',components: { 'm-card': Card },data() {return {swiperOptions: {slidesPerView: 1,autoplay: {disableOnInteraction: false,delay: 2000,},pagination: {el: '.swiper-pagination',clickable: true,},},isCollapse: true,// 定义ListCard组件的数据结构// newsList的简单写法,新建数组5填充1,再map循环替换成对象newsCats: [{_id: 1,name: '热门',newsList: new Array(5).fill(1).map((v) => ({_id: v + 201,categoryName: '赛事',title: '景明柳垂莺娇,峡谷好礼随春报到',date: '06/01',})),},{_id: 2,name: '新闻',newsList: new Array(5).fill(2).map((v) => ({_id: v + 202,categoryName: '赛事',title: '景明柳垂莺娇,峡谷好礼随春报到',date: '06/01',})),},],// 后台数据// newsCats: [],herosCats: [],};},created() {this.fetchNewsCats();},mounted() {console.log('Current Swiper instance object', this.swiper);//   this.swiper.slideTo(3, 1000, false);},computed: {swiper() {return this.$refs.mySwiper.$swiper;},},methods: {async fetchNewsCats() {const res = await this.$http.get('news/list');this.newsCats = res.data;},switchActive() {this.isCollapse = !this.isCollapse;},},};
</script>
<style lang='scss' scope>@import '../style/variables.scss';//  重新定义一个class,便于单独管理各个页面的swipers.pagination-home {.swiper-pagination-bullet {display: inline-block;opacity: 1;border-radius: 0.1538rem;background-color: map-get($colors, 'white');//   background-color: #ffffff;&.swiper-pagination-bullet-active {background: map-get($colors, 'info');}}}.nav-icons {border-top: 1px solid $border-color;border-bottom: 1px solid $border-color;.nav-item {width: 25%;// 取消右侧的边框border-right: 1px solid $border-color;&:nth-child(4n) {border-right: none;}}}.toggleActive {height: 60px;overflow: hidden;}.fade-enter {opacity: 0;}.fade-leave {opacity: 1;}.fade-leave-active,.fade-enter-active {transition: opacity 0.9s;}
</style>

3.15 web首页英雄列表提取官方数据

// 简化版
$$('.hero-nav > li').map(( li,i)=>{return {heros:$$('li',$$('.hero-list')[i]).map(el=>{return {name:$$('h3',el)[0].innerHTML}}),name:li.innerText}})
// 获取img链接,并转成json数据
JSON.stringify($$('.hero-nav > li').map(( li,i)=>{return {heros:$$('li',$$('.hero-list')[i]).map(el=>{return {name:$$('h3',el)[0].innerHTML,avatar:$$('img',el)[0].src}}),name:li.innerText}}))
发布评论

评论列表 (0)

  1. 暂无评论