都是类比巩固 …
↓ 在server/interface
中创建接口search.js
来搭建关于搜索推荐的接口
/**
* descripe: 搜索栏及推荐列表的接口设置
* author: umbrella
* date: 2018-6-28PM21:39:01
* --------------------说明-----------------------
* --koa-router路由 || 引入封装的axios数据通讯 || 引入相对应的线下数据表Poi
* --定义路由主体的前缀
* --定义接口 获取搜索时显示的内容接口top || 根据定位获取推荐景点接口hotPlace
* --导出路由router
*/
import Router from 'koa-router'
import axios from './utils/axios'
import Poi from '../dbs/models/poi'
// 请求页面接口请求前缀
let router = new Router({
prefix: '/search'
})
// 获取搜索时显示的内容接口
router.get('/top',async (ctx) =>{
let{status,data:{top}} = await axios.get('http://cp-tools.cn/search/top?sign',{
params:{
input: ctx.query.input,
city: ctx.query.city
}
})
ctx.body = {
top: status === 200 ? top : []
}
})
// 根据定位获取推荐景点接口
router.get('/hotPlace', async(ctx) =>{
let city = ctx.store ? ctx.store.geo.position.city : ctx.query.city;
let{status,data:{result}} = await axios.get('http://cp-tools.cn/search/hotPlace?sign',{
params:{
city
}
})
ctx.body = {
result: status === 200 ? result : []
}
})
export default router
从此有关search中需要涉及的接口就写在search.js
中
↓ 之后记得index.js
配置导入的search的路由
import search from './interface/search'
app.use(search.routes()).use(search.allowedMethods())
如果需要操作数据库的话(操作线下),就要设计对应的数据库表pois对应数据的表结构
然后项目中进行代码调用:
import mongoose from 'mongoose'
const Schema = mongoose.Schema
const Poi = new Schema({
name: {
type: String // 景点名称
},
province: {
type: String // 景点所在省份
},
city: {
type: String // 景点所在城市
},
county: {
type: String // 景点所在市级
},
areaCode: {
type: String // 景点所在区域代码
},
tel: {
type: String // 景点联系电话
},
area: {
type: String // 景点区域名称
},
addr: {
type: String // 景点具体地址
},
type: {
type: String // 景点类型名
},
module: {
type: String // 景点具体详情
},
longtide:{
type: Number // 景点经度
},
latitude:{
type: Number // 景点纬度
}
})
export default mongoose.model('Poi', Poi)
最后记得如果要使用Poi的话就要在search路由中进行导入
这里说一下两种使用koa-router请求数据的写法
router.get('/top',async(ctx) => {
let{status,data:{top}} = await $axios.get(`http://cp-tools/search/top?input=${ctx.query.input}&city=${ctx.query.city}&sign`)
})
router.get('/top', async(ctx) => {
let{status,data:{top}} = await $axios.get('http://cp-tools/search/top?sign',{
params:{
input: ctx.query.input,
city: ctx.query.city
}
})
)
说一点(重要):ctx.query
是get请求拿页面数据的方式 || ctx.request.body
则是post
这样就配置好了一个线上的请求接口,那么我们可以根据我们写的接口params去使用postman测试一下接口是否可以返回值:
能返回值就说明请求成功啦
↓ 配置vuex中的store三者关系:
const state = () => ({
menu: [],
hotPlace: []
})
const mutations = {
setMenu(state, val) {
state.menu = val
},
setHotPlace(state, val) {
state.hotPlace = val
}
}
const actions = {
setMenu: ({
commit
}, menu) => {
commit('setMenu', menu)
},
setHotPlace: ({
commit
}, hotPlace) => {
commit('setHotPlace', hotPlace)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
↓ 对应创建store实例
/**
* descripe: 创建store实例提供给页面调用Store库中的方法及获取内部的数据
* author: umbrella
* data: 2019-6-30AM13:07:48
* -------------说明--------------
* -- 导入Vue、Vuex必备包 || 其次导入需要被页面调用的Store库geo、home
* -- 配置各自管理的模版名称geo、home,之后页面拿state中的数据就是通过modules区分,
* 例如拿geo中state容器中的数据city → $store.state.geo.position.city
* -- 使用nuxt中的nuxtServerInit生命周期函数 → 进行页面载入时就已经执行了Store中相关的路由方法
* -- 注意点:由于页面实例还没渲染到页面,因此只能通过app根节点进行$axios的请求
*/
import Vue from 'vue'
import Vuex from 'vuex'
import geo from './modules/geo'
import home from './modules/home'
Vue.use(Vuex)
const store = () => new Vuex.Store({
modules: {
geo,
home
},
actions: {
async nuxtServerInit({
commit
}, {
req,
app
}) {
const {
status: status3,
data: {
result
}
} = await app.$axios.get('/search/hotPlace', {
params: {
city: app.store.state.geo.position.city.replace('市', '')
}
})
commit('home/setHotPlace', status3 === 200 ? result.slice(0, 4) : [])
}
}
})
↓ 既然调试接口成功,那我们就把这个返回的数据写在我们的页面上(这个数据是搜索时请求的数据,那么我们找到搜索栏界面components->public->header->searchbar.vue)
html:
<dl v-if="isHotPlace" class="hotPlace">
<dt>热门搜索dt>
<dd v-for="(item,index) in $store.state.home.hotPlace" :key="index">{{item.name}}dd>
dl>
javascript:
input: _.debounce(async function() {
let self = this;
let city = self.$store.state.geo.position.city.replace("市", "");
self.searchList = [];
let {
state,
data: { top }
} = await self.$axios.get("/search/top", {
params: {
input: self.search,
city
}
});
self.searchList = top.slice(0,10)
}, 300)
总结一下:
这里页面就直接通过$store.state.home.hotPlace
拿到搜索查询接口top的数据,然后input中的逻辑就是要完成输入进行时拿到输入框的字段进行接口的请求,拿到对应查询的数据,这里涉及的是搜索功能,所以要使用一个延迟节流函数插件库lodash
中使用debounce
完成这部分的逻辑,注意要截取掉city所带的’市’字段,不然请求不到的哦~
同样写推荐图文数据的接口search.js
router.get('/resultsByKeywords', async(ctx)=>{
const {city,keyword} = ctx.query;
let {status,data:{count,pois}} = await aixos.get('http://cp-tools.cn/search/resultsByKeyword?sign',{
params:{
city,
keyword
}
})
ctx.body = {
count: status === 200 ? count : 0,
pois: status === 200 ? pois: []
}
})
小提示:凡是本地服务请求线上数据库的都可以进行postman测试接口
测试完接口后,我们就可以把数据实现在页面中啦,找到对应推荐部分的代码artistic.vue
1、巧用数据源event:进行页面便签元素的获取!
2、前端自己定个字段用于展示自己的页面,如果后端改字段了就直接修改请求接口return中的值即可!
鼠标经过标签时,必须等待请求数据下来并且展示在页面是才展示
methods: {
over: async function(e) {
let dom = e.target;
let tag = dom.tagName.toLowerCase();
let self = this;
if (tag === "dd") {
this.kind = dom.getAttribute("kind");
let keyword = dom.getAttribute("keyword");
let {
status,
data: { count, pois }
} = await self.$axios.get("/search/resultsByKeywords", {
params: {
keyword,
city: self.$store.state.geo.position.city
}
});
if (status === 200 && count > 0) {
let r = pois
.filter(item => item.photos.length)
.map(item => {
return {
title: item.name,
pos: item.type.split(";")[0],
price: item.biz_ext.cost || "暂无",
img: item.photos[0].url,
url: "//abc.com"
};
});
self.list[self.kind] = r.slice(0, 9);
} else {
self.list[self.kind] = [];
}
}
}
}
解决一个BUG实现:加载页面是通过async-await的异步配合mounted加载推荐图文部分的用户体验,不然会出现页面加载完了,推荐的图文还没有展示出来
async mounted() {
let self = this;
let {
status,
data: { count, pois }
} = await self.$axios.get("/search/resultsByKeywords", {
params: {
keyword: "景点",
city: self.$store.state.geo.position.city
}
});
if (status === 200 && count > 0) {
let r = pois
.filter(item => item.photos.length)
.map(item => {
return {
title: item.name,
pos: item.type.split(";")[0],
price: item.biz_ext.cost || "暂无",
img: item.photos[0].url,
url: "//abc.com"
};
});
self.list[self.kind] = r.slice(0, 9);
} else {
self.list[self.kind] = [];
}
}
❤ 项目源码 ❤
GitHub地址:https://github.com/Umbrella001/mtapp