Vue+Node.js开发Xmall商城——Day1

今天是个美好的日子,因为今天又想到了一个新的项目——XMall商城。

特此记录项目开发全过程

商城官网传送门 http://xmall.exrick.cn/#/home

本项目目录基于Vue-cli脚手架搭建

vue create xmallshop

项目依赖选择了vueRouterVueX,在搭建完成后安装了如下依赖包:

    "axios": "^0.21.1",
    "core-js": "^3.6.5",
    "element-ui": "^2.15.1",
    "less-loader": "^5.0.0",
    "node-sass": "^4.13.0",
    "sass-loader": "^8.0.0",
    "vue": "^2.6.11",
    "vue-lazyload": "^1.3.3",
    "vue-router": "^3.2.0",
    "vuex": "^3.4.0"

然后。分析了一下路由结构,创建项目完以后第一件事肯定是分配路由啦,观察了一下官网发现顶部双级导航栏在切换导航菜单时始终保持,因此Mheader(导航栏)作为了一个component公共路由,再把导航栏里每个菜单单独分配了一个路由,如图
在这里插入图片描述
路由划分如下:

const routes = [
  {
    path:'/',
    redirect:'/home',
    component:Home
  },
  {
    path:'/home',
    component:Home
  },
  {
    path:'/goods',
    component:Goods
  },
  {
    path:'/thanks',
    component:Thanks
  },
  {
    path:'/login',
    component:Login
  },
  {
    path:'/user',
    component:User
  },
  {
    path:'/cart',
    component:Cart
  }
]

路由分配完毕,今天的任务是首页(/home)的页面设计,第一部分是轮播图用的element-UI的组件,很方便所以也没有单独创建组件,直接在home.vue里贴上去了。

<!-- 轮播图 -->
            <div class="banner">
                <el-carousel indicator-position="outside" height='480px'>
                    <el-carousel-item v-for="(item,index) in banner" :key="index">
                        <img class = "img1 a" v-if="item.picUrl" :src = "item.picUrl">
                        <img class = "img2 a"  v-if="item.picUrl2" :src = "item.picUrl2">
                        <img class = "img3 a"  v-if="item.picUrl3" :src = "item.picUrl3">
                    </el-carousel-item>
                </el-carousel>
            </div>
<!-- 轮播图over -->

关于轮播图里的图片数据以及接下来卡片、列表里的数据是从官网拿的接口,在本地创了JSON文件,再用node.js访问导出接口后交给前端去get请求的,后端接口导出部分如下:

const fs = require('fs');
module.exports = {
    devServer:{
        before(app,serve){
            app.get('/api/goods/home',(req,res)=>{
                fs.readFile('./db/home.json','utf8',(err,data)=>{
                    if(!err){
                        res.json(JSON.parse(data));
                    }
                })
            })
            app.get('/api/goods/allgoods',(req,res)=>{
                fs.readFile('./db/allgoods.json','utf8',(err,data)=>{
                    if(!err){
                        res.json(JSON.parse(data));
                    }
                })
            })
            
        }
    }
}

测试接口用了postman,真的很好用也很方便,总比在控制台里看要舒服很多。
在这里插入图片描述

今天用到了api/goods/home的接口,首页里的所有数据都是从这里得到的,包括了轮播图URL以及各种商品的信息、价格。值得一提的是在前端接口请求一般都会在vcreated钩子函数中请求,原因是所有DOM生成完毕后可直接渲染。

关于接口的请求,用到的则是axios,由于请求比较频繁一直会用到,因此我在项目VUE全局里自定义了一个$http用于请求。

Vue.prototype.$http = axios;

请求方式如下:

async created () {
        const res = await this.$http.get("/api/goods/home");
        if(res.data.code === 200){
            this.result = res.data.result;
            this.banner = res.data.result[0].panelContents;
            console.log(this.banner);
        }
        console.log(res);
    },

接下来页面中商品列表及卡片仔细观察其实结构是类似的,只需要v-for循环渲染即可,由于每一板块在json数据中有判断,如热门活动的item.type为1、周边品牌的item.type为2等等。因此循环渲染就完事。

并且有很多相同样式的卡片定义了卡片组件MShelf方便公用。

<div v-for = "(item,index) in result" :key="index">
          <!-- item.type为1时是热门活动 -->
           <div class="activity-panel" v-if="item.type==1">
               <el-row>
                   <el-col class="content" :span="8" v-for="(o,index) in item.panelContents" :key="index" width="305px">
                       <el-card :body-style="{ padding: '0px'}">
                           <img :src="o.picUrl" class="i">
                           <a href="#" class="cover-link"></a>
                       </el-card>
                   </el-col>
               </el-row>
           </div>
           <!-- 热门活动渲染over -->
           <section class="w mt30 clearfix" v-if="item.type==2">
                <m-shelf :title="item.name">
                    <div slot = "content" class = "hot">
                       <mall-goods v-for = "(o,index) in item.panelContents" :key="index" :goods="o"></mall-goods>
                   </div>
                </m-shelf>
           </section>
           <section class="w mt30 clearfix" v-if="item.id==2||item.id==10||item.id==3" :style="watchStyle(item.id)">
               <m-shelf :title="item.name">
                   <div slot = "content" class="floors">
                       <div class="imgbanner" v-for="(o,index) in item.panelContents" :key="index" v-show="o.type==2||o.type==3">
                           <a href="#" class="cover-link"></a>
                           <img :src="o.picUrl">
                       </div>
                       <mall-goods v-for="y in item.panelContents" :key="y.id" v-show="y.type==0" :goods="y"></mall-goods>
                   </div>
               </m-shelf>
           </section>
       </div>
 </div>

最后的底部与导航栏一样,在菜单的切换时都会存在,因此创建了一个Footer组件在每个路由组件中存放。

明天继续加油吧…
学习前端真的很快乐,有兴趣不怕学不会,休息~


版权声明:本文为m0_46995864原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。