作者

一、简介

本次项目以Node.js + Express框架提供接口,后台使用分离模式,用ElementUI做后台模板, 前端使用微信小程序实现的一个扫码购物的项目。

二、项目搭建

后端接口项目搭建,请参考我的另外一篇文章:https://itfun.tv/news/150

接下来,我们演示前端后台项目搭建。

1、在基于node环境的laragon集成环境中,终端任意目录执行命令

npm install -g cnpm --registry=https://registry.npm.taobao.org

//如果淘宝镜像不能用,请使用阿里镜像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

cnpm install -g @vue/cli

vue ui

注意:如果你电脑是第一次创建vue项目,上面命令启动后,会自动从浏览器中打开新建项目页面。

如果你电脑之前已经安装过vue的项目,执行上面的命令后,浏览器会自动打开一个项目仪表盘的管理页面。

点击左上角的按钮,选择 Vue项目管理器

点击创建

选择项目路径

点击底下的创建项目,进入如下图片

选择手动

选择第一项和第四项

勾上history router

2、引入elementUI,参考文档:https://element.eleme.cn/#/zh-CN/component/installation

npm i element-ui -S

main.js中写入以下内容:

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI);

修改路由

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/admin/Home.vue'

Vue.use(Router)

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/admin',
      name: 'home',
      component: Home
    },
    {
      path: '/product',
      name: 'product',
      component: () => import('./views/admin/product/Home.vue')
    },
    {
      path: '/product/create',
      name: 'productCreate',
      component: () => import('./views/admin/product/Create.vue')
    }
  ]
})

views文件夹中新建admin/Home.vue组件,引入element自带button样式,启动项目,刷新页面:http://localhost:8080/#/admin 你会发现样式已加载。

3、页面处理,为了节省做页面的时间,我这里直接贴上自己写好的模块代码,仅供参考。

修改views/admin/Home.vue代码如下:

<template>
    <div>
        <el-alert class="home_desc" title="Walsmart后台管理系统" type="success" :closable="false"
                  description="这是一个基于Node.js + ElementUI使用接口开发模式开发的一套后台管理系统。主要业务用于扫码购物的各个模块,如:商品管理、分类管理、用户管理等。
          本次系统还在不断完善中,敬请期待....
        "show-icon>
        </el-alert>

        <el-alert
                title="辅助工具和资料"
                type="warning"
                description="1、phpstrom编辑器 2、mamp集成开发环境 3、api接口测试软件postman"
                :closable="false"
                show-icon>
        </el-alert>

        <div class="hengxian"></div>
    </div>
</template>

<style>
    .el-alert__title.is-bold {
        font-weight: 900;
    }

    .el-alert__title {
        font-size: 25px;
        line-height: 30px;
    }

    .el-alert .el-alert__description {
        font-size: 14px;
        margin: 10px 0 0;
    }

    .el-alert--warning{
        margin-top: 10px;
    }
    .some_total{
        margin-top: 50px;
    }
    .hengxian {
        margin-top: 20px;
        border-top: 1px solid #eeeeee;
    }
</style>

admin文件夹下创建App.vue文件,代码如下:

<template>
    <div id="main" style="height: 100%">
        <el-container>
            <el-header>
                <AdminHeader></AdminHeader>
            </el-header>
            <el-container>
                <el-aside width="200px">
                    <Aside></Aside>
                </el-aside>
                <el-main class="animate_fix">        <!--添加动画效果-->
                    <transition name="fade">
                        <router-view/>
                    </transition>
                </el-main>
            </el-container>
        </el-container>
    </div>
</template>

<script>
    import Aside from '../../components/shared/Aside.vue'
    import AdminHeader from '../../components/shared/Header.vue'

    export default {
        name: 'App',
        components: {
            Aside,
            AdminHeader
        },
        data() {
            return {}
        }
    }
</script>

<style>
    body{
        height: 100%;
    }
    .el-header {
        text-align: center;
        line-height: 60px;
        background-color: rgb(84, 92, 100);
    }

    .el-aside {
        background-color: #D3DCE6;
        color: #333;
        text-align: center;
        background-color: #fff;
    }

    .el-menu {
        border: none;
    }

    .el-main {
        background-color: #fff;
        color: #333;
        padding: 0;
    }

    html, body {
        height: 100%;
    }

    body > .el-container {
        height: 100%;
    }

    .el-container {
        height: 100%;
    }

    .el-aside {
        height: 100%;
        background-color: rgb(84, 92, 100)
    }

    .el-container:nth-child(5) .el-aside,
    .el-container:nth-child(6) .el-aside {
        line-height: 260px;
    }

    .el-container:nth-child(7) .el-aside {
        line-height: 320px;
    }

    .el-aside::-webkit-scrollbar {
        display: none;
    }

    .has-gutter th div.cell {
        text-align: center;
    }

    .animate_fix {
        position: relative;
        /*width: 100%;*/
    }

    .animate_fix > div {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        padding: 20px;
    }

    .el-card__body {
        padding: 5px;
    }

    .el-collapse-item:last-child {
        margin: 0;
    }

    .el-collapse-item__header {
        height: 38px;
        line-height: 38px;
    }

    .el-collapse-item__arrow {
        line-height: 38px;
        height: 38px;
    }

    .el-footer {
        margin-top: 30px;
        text-align: center;
    }

</style>

main.js中引入此文件

import App from './views/admin/App.vue'

components/shared文件夹下,创建Aside.vueHeader.vue两个文件, 代码分别如下:

<template>
    <el-menu
            default-active="/"
            class="el-menu-vertical-demo"
            :router="true"
            background-color="#545c64"
            text-color="#fff"
            active-text-color="#ffd04b">

        <el-menu-item index="/admin">
            <span slot="title">
                <i class="el-icon-s-home"></i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
        </el-menu-item>

        <el-submenu index="1">
            <template slot="title">
                <i class="el-icon-shopping-cart-full"></i>
                <span>商城中心</span>
            </template>
            <el-menu-item-group>
                <el-menu-item index="/product"><i class="el-icon-s-goods"></i>商品管理</el-menu-item>
                <el-menu-item index="/courses"><i class="el-icon-date"></i>商品分类</el-menu-item>
            </el-menu-item-group>
        </el-submenu>
    </el-menu>
</template>
<template>
    <el-menu index="0" class="el-menu-demo" mode="horizontal" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
        <div class="menu_icon">
            <i class="el-icon-loading"></i> Walsmart
        </div>
        <el-submenu index="1">
            <template slot="title">huangdj 管理员</template>
            <el-menu-item index="1">退出</el-menu-item>
        </el-submenu>
    </el-menu>

</template>

<style scoped>
    .el-menu--horizontal > .el-submenu {
        float: right;
    }

    .menu_icon {
        float: left;
        width: 200px;
        color: #D3DCE6;
        text-align: center;
        font-size: 30px
    }
</style>

4、跨域处理

第一种方法:回到后端项目,进入根目录,安装跨域请求包

cnpm install cors --save

app.js中,加入如下代码:

var cors = require('cors'); 

app.use(cors());    

第二种方法:在当前前端项目的config/index.js文件中,找到dev代码块,做如下配置:

assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
  '/api': {
    target: 'http://localhost:3000',
    changeOrigin: true,
    pathRrewrite: {
      '^/api': ''
    }
  }
},

以上两种方法选择其一。不管你使用的是哪种方法,接下来还是在前端项目目录中执行如下命令:

cnpm install axios --save

安装完后`main.js`文件中引入`axios`

import axios from 'axios'
Vue.prototype.axios = axios;

浏览器访问:http://localhost:8080/#/admin,你会看到如下页面:

5、接口数据渲染

以后台首页为例,去加载所有分类,在Home.vue添加如下代码:

<script>
  export default {
    data() {
      return {

      }
    },
    created() {
      this.init()
    },
    methods: {
      init() {
        //所有分类
        this.axios.get(`http://localhost:3000/admin/categories`)
          .then((res) => {
            console.log(res)
          })
      },
    }
  }
</script>

查看终端:如图

至此,后台分离项目搭建已完成!

另附:小米商城分离版项目搭建

1、项目创建,按照上面的步骤来即可。

2、接下来,把准备好的项目模板拿进来,样式放入public文件夹,首页模板覆盖之前的index.html。浏览器就能看到样式了。 然后把footer组件拿到components里面,需要用的页面引入即可。例如在Home.vue里面,做如下引入:

<script>
import Footer from '@/components/Footer.vue'

export default {
  name: 'home',
  components: {
    Footer
  }
}
</script>

然后在该页面上对应位置就可以这样使用 <Footer/>

这只是一种搞法,其实还可以全局引入。在main.js中,

import Footer from '@/components/Footer.vue'

Vue.component('my-footer', Footer);

然后在该页面上对应位置就可以这样使用 <my-footer/>

接下来,安装axios,进入项目目录,执行命令

cnpm i axios -S

引入axios,在main.js中添加如下代码

import axios from 'axios'

Vue.prototype.axios = axios;

配置访问的url接口链接地址,在项目目录中创建.env文件,里面写上如下代码:

VUE_APP_URL=http://127.0.0.1:8000

然后在src文件夹中创建http.js文件,里面添加如下代码:

import axios from 'axios'

axios.defaults.baseURL = process.env.VUE_APP_URL;      //获取.env配置的URL地址

export default axios;

修改axios.js中的代码:

把这行import axios from 'axios' 替换成  import axios from '.http.js'

router.js中的路由推荐使用懒加载模式,示例如下:

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: () => import('./views/Home.vue')
    },
    {
      path: '/product/category',
      name: 'category',
      component: () => import('./views/product/Category.vue')
    },
    {
      path: '/product/list/:id',
      name: 'list',
      component: () => import('./views/product/List.vue')
    },
    {
      path: '/product/:id',
      name: 'show',
      component: () => import('./views/product/Show.vue')
    },
    {
      path: '/cart/index',
      name: 'index',
      component: () => import('./views/cart/Index.vue')
    },
  ]
})

修改Home.vue组件里面的script代码如下:

<script>
    export default {
        data() {
            return {
                data: {}
            }
        },
        //初始化
        created() {
            this.init();
        },
        updated() {
            $('.flexslider').flexslider({
                animation: "slide",
                directionNav: false
            });
        },
        methods: {
            init: function () {
                this.axios.get(`/api`).then((res) => {
                    // console.log(res)
                    this.data = res.data
                })
            }
        }
    }
</script>

转载请注明,来自https://itfun.tv/news/154