实现功能
- 点击页面搜索框输入内容
- 回车将输入数据发送给后台
- 后台拿到数据后存入数据库
代码如下
项目目录:
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')