elementUI、vue、koa、mongoose实现简单前后台测试接口

实现功能

在这里插入图片描述

  1. 点击页面搜索框输入内容
  2. 回车将输入数据发送给后台
  3. 后台拿到数据后存入数据库

代码如下

项目目录:
在这里插入图片描述

1. package.json

{
  "name": "test1",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "startnode": "node ./server/config.js",
    "start": "nodemon ./server/config.js"
  },
  "dependencies": {
    "axios": "^0.19.2",
    "core-js": "^3.6.5",
    "element-ui": "^2.13.2",
    "jquery": "^3.5.1",
    "koa": "^2.13.0",
    "koa-bodyparser": "^4.3.0",
    "koa-router": "^9.0.1",
    "koa2-cors": "^2.0.6",
    "mongoose": "^5.9.20",
    "vue": "^2.6.11"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.4.0",
    "@vue/cli-plugin-eslint": "~4.4.0",
    "@vue/cli-service": "~4.4.0",
    "babel-eslint": "^10.1.0",
    "babel-register": "^6.26.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "nodemon": "^2.0.4",
    "vue-template-compiler": "^2.6.11"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {},
    "globals": {
      "$": true
    }
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

2. config.js(数据库连接、node服务启动、跨域处理、路由引入)

/server/config.js

const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const mongoose = require('mongoose');
const cors = require('koa2-cors');
const router = require('./router');

const db = 'mongodb://localhost:27017/test1';
mongoose.connect(db);

const app = new Koa();
app.use(bodyParser());
app.use(cors({
    origin: function (ctx) {
        return "*"; // 允许来自所有域名请求
    },
    exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
    maxAge: 5,
    credentials: true,
    allowMethods: ['GET', 'POST', 'DELETE'], //设置允许的HTTP请求类型
    allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}));
app.use(router.routes());
app.use(router.allowedMethods());

app.listen(3000)

3. router.js(路由配置)

/server/router.js

const Router = require('koa-router');
const Search = require('./controllers/search');

let router = new Router({
    prefix: '/api'
})
router.post('/search', Search.addSearch);

module.exports = router;

4. search.js(控制器)

/server/controllers/search.js

let mongoose = require('mongoose');
const bodyParser = require('koa-bodyparser');
const Search = require('../models/search');

exports.addSearch = async (ctx)=>{
    let data = ctx.request.body;
    let id = `s${Math.random().toString().slice(2,4)}`;
    let search = new Search({
        sid:id,
        name:data.search
    })
    console.log(Search)

    let search1;
    if(search){
        search1 = await search.save();
    }
    
    if(search1){
        ctx.body = {
            code:0,
            msg:'success'
        }
    }else{
        ctx.body = {
            code:1,
            msg:'error'
        }
    }
}

5. search.js(表)

/server/models/search.js

let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let search = new Schema({
    sid:String,
    name:String
})
let Search = mongoose.model('Search',search);
module.exports = Search;

6. Nav.vue

<template>
  <el-container>
    <el-header>
      <el-row class="searchcontainer">
        <i class="el-icon-search searchicon" v-show="ifShow">搜索</i>
        <el-input type="text" clearable v-model="search" @focus="hideSearchText" @blur="showSearchText" @change="sendSearch"></el-input>
      </el-row>
      <el-row type="flex" justify="space-between" class="address">
        <el-col :span="8">
          <i class="el-icon-location-outline"></i>xxxxxx<i class="el-icon-arrow-right"></i>
        </el-col>
        <el-col :span="8">
          <el-button-group>
            <el-button v-for="(item,index) in selectTypes" :key="index" :type="item.active?'danger':''" size="mini" @click="selectType" :data-id="item.id">{{item.content}}</el-button>
          </el-button-group>
        </el-col>
      </el-row>
    </el-header>
    <el-main></el-main>
    <el-footer>
      <el-row>
        <el-col :span="6"><div class="foot-nav-item"><i class="el-icon-house"></i><span>首页</span></div></el-col>
        <el-col :span="5"><div class="foot-nav-item"><i class="el-icon-menu"></i><span>分类</span></div></el-col>
        <el-col :span="6"><div class="foot-nav-item"><i class="el-icon-goods"></i><span>购物袋</span></div></el-col>
        <el-col :span="6"><div class="foot-nav-item"><i class="el-icon-user"></i><span>订单</span></div></el-col>
      </el-row>
    </el-footer>
  </el-container>
</template>

<script>

export default {
  name: 'Nav',
  data:function(){
    return {
      btn:'test',
      selectTypes:[
        {
          id:1,
          content:'自提',
          active:false
        },
        {
          id:2,
          content:'配送',
          active:true
        }
      ],
      search:'',
      ifShow: true
    }
  },
  methods:{
    selectType:function(e){
      console.log(e)
      if(e.currentTarget.dataset.id == 1){
        this.selectTypes[0].active = true
        this.selectTypes[1].active = false
      }else{
        this.selectTypes[0].active = false
        this.selectTypes[1].active = true
      }
    },
    hideSearchText:function(){
      this.ifShow = false
    },
    showSearchText:function(){
      this.ifShow = true
    },
    sendSearch:function(){
      this.$http({
        url:'http://localhost:3000/api/search',
        method:'post',
        data:{
          search:this.search
        }
      }).then(function(res){
        console.log(res)
      })
    }
  }
}
</script>

<style>
  .searchcontainer{
    position: relative;
    margin-bottom: 10px;
  }
  .searchicon{
    position: absolute;
    z-index: 1;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
  .foot-nav-item{
    display: flex;
    flex-direction: column;
  }
  .address>div:first-child{
    text-align: left;
  }
  .address>div:last-child{
    text-align: right;
  }
</style>

7.App.vue

<template>
  <div id="app">
    <Nav/>
  </div>
</template>

<script>
import Nav from './components/Nav.vue'

export default {
  name: 'App',
  components: {
    Nav
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

8. main.js

import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import axios from 'axios'
import App from './App.vue'

Vue.use(ElementUI)
Vue.prototype.$http = axios

Vue.config.productionTip = false
new Vue({
  render: h => h(App),
}).$mount('#app')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值