我们继续前两节的开发。本节教程实现的效果如下:
效果很简单,但是实现起来却要用到Vue的很多知识,下面我们将一步一步的实现这个效果。
首先这些城市的信息都是从后台的server里面获取的,所以我们需要一个后台,后台的代码可以从
https://github.com/EzrealDeng/Taopiaopiao里面的server 文件夹获取,这个server端具体怎么实现的我们暂时不用关心,只需要知道这是一个可以返回我们需要的数据的后台服务即可。
下载完后进入文件夹执行:
npm install //安装所有的包
npm run start //启动后台服务
即可启动服务,(如果启动过程中出错,可以使用npm run start:strict 启动,或者升级node版本,默认的是9090端口,可以手动进行修改)。
成功启动的话我们就有了一个可以使用的数据后台了。那么Vue如何访问这个接口的呢,我们这里使用vue-resource(类似于Jquery里的ajax的功能)进行访问后台接口。vue-resource的使用方式类似下面的例子:
this.$http.get('/movie/swiper').then(function(res){ //返回的是promise对象,res为返回的对象 console.log(res); this.images = res.body.data.data.returnValue; console.log(this.images); })
有了这个我们就可以和后台进行数据交互了,但是还有一个问题,我们的开发是vue脚手架自动搭建的一个基于Express的服务,我们的前端代码实际上直接访问的都是这个前端项目的后台,想要直接访问我们刚才搭建的后台会有跨域问题的,怎么办呢?幸好有一个叫做http-proxy的东西,可以帮我们实现代理,将我们要访问的接口都映射到真正的服务器上,后端进行跨域问题的解决。而且Vue脚手架也帮我们集成了这个插件,只要在配置文件里修改即可。这个文件在:config/index.js里,修改这个文件里的proxyTable如下
.....//省略 dev: { env: require('./dev.env'), port: 8080, autoOpenBrowser: true, assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: { '/movie/coming': 'http://localhost:9090', '/movie/hot': 'http://localhost:9090', '/movie/info': 'http://localhost:9090', '/movie/evaluation': 'http://localhost:9090', '/movie/cinema': 'http://localhost:9090', '/movie/cinema_detail': 'http://localhost:9090', '/movie/swiper': 'http://localhost:9090', '/movie/city': 'http://localhost:9090' }, ...//省略
到现在为止,接口的访问问题已经解决了。
还有最后一个准备知识需要介绍下,那就是Vuex,这是个啥呢?就是个状态管理机,由于Vue好多个组件可能会共用同一个状态信息,例如我们的淘票票,选择城市的这个组件需要知道当前的城市信息,而每个城市会有当前不同的上映的电影,这个反应当前热映电影的组件也需要知道这个信息,如何保持数据的同步,光靠组件之间的通信将会十分复杂,所以有了Vuex这个东西,具体如何使用可以去看https://vuex.vuejs.org/zh-cn/官网的介绍。本例中用到的地方我会写上注释。接下来开始正式的编码吧。
上面我们介绍了这么多的东西,使用起来当然得先一一的安装一遍。
npm install vuex --save //vuex npm install vue-resource --save //vue-resource
另外我们选择城市的组件用到了mint-ui的Vue组件库,所以要也要安装。
npm install mint-ui //mint-ui
接下来新建文件和目录如下:
主要是新建立home/city.vue和store文件夹。city.vue是我们的选择城市的组件,store存放的是Vuex状态管理文件。
依次修改city.vue如下:
if="$store.state.city.show"> 选择城市 × for="city in cityList" key="city.id"> for="name in city.data" key="name.id">
store/city/actions.js如下:
import Vue from 'vue' export default {
//异步的更新城市信息 updateCityAsync ({ commit, state }, {city}) { //commit对象可以用来触发mutations里面的同步更新城市方法 if (!city.name) { city.name = state.name city.rN = state.rN } return Vue.http.get(`/movie/hot/?city=${city.rN}`).then((response) => { let data = response.data let lists = data.data.data.returnValue //模拟索引数据的id号 lists.forEach((item, index) => { item.mID = index }) city.data = lists commit('UPDATE', { city }) // 更新城市信息 }) } }
mutations.js如下:
export default{ UPDATE (state , { city }){ //根据传入的city对象来改变状态 if(city.name){ state.name = city.name; state.data = city.data; state.rN = city.rN; } state.show = false; }, showCityList (state) { //显示城市选择 state.show = true } }
store/loading/mutations.js如下:
//loading组件
import { Indicator } from 'mint-ui'; export default { pushLoadStack (state) { Indicator.open({ text: 'loading...', spinnerType: 'snake' }); state.stack.push(1) }, completeLoad (state) { //完成加载 let stack = state.stack stack.pop() if (!stack.length) { //延时为了更好显示loading效果 setTimeout(() => { Indicator.close() }, 500) } } }
然后再修改store下的index.js,这个文件是所有的mutations和actions的总出口。
import Vue from 'vue' import cityMutations from './city/mutations' import cityAcions from './city/actions' import loadingMutations from './loading/mutations' import Vuex from 'vuex' Vue.use(Vuex) //vue插件只需要在这里use一次 const cityGetters = { movies: state => state.data, cityName: state => state.name } const city = { state: { name: '北京', show: true, rN: 'bj', data: [] }, actions: cityAcions, mutations: cityMutations, getters: cityGetters } const loading = { state: { stack: [] }, mutations: loadingMutations } export default new Vuex.Store({ modules: { city, loading } })
然后再修改src下的main.js如下:
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import Mint from 'mint-ui'; import store from './store' import VueResource from 'vue-resource' import 'mint-ui/lib/style.css' Vue.config.productionTip = false Vue.use(Mint) Vue.use(VueResource) /* eslint-disable no-new */ new Vue({ el: '#app', router, store, template: '', components: { App } })
然后再使用我们刚才建立的city组件,修改views/movie.vue如下:
{{ $store.state.city.name }}正在热映即将上映
所有文件修改完成之后重新启动项目,不出意外的话应该就会完成我们开头的效果了。
这里面具体的city.vue的实现可能有些地方看不太清楚,没关系,再后面的章节后我们会一步步自己实现简单的类似的组件。
谢谢阅读,如果有问题欢迎在评论区一起讨论。
更新: 由于写一篇教程还是需要费一定的时间的,工作繁忙后续可能没有时间更新这个系列的文章了,但是整个淘票票的代码我是有更新的,需要的话可以在我的gitHub上查看:
https://github.com/EzrealDeng/Taopiaopiao
不能继续更新博客还请大家原谅,有问题的话可以留言一起讨论
注:本文出自博客园 https://home.cnblogs.com/u/mdengcc/ ,转载请注明出处。