我的项目简介
蜘蛛电影次要是仿猫眼电影的一个vue我的项目次要性能:1. 城市定位2. 展现正在热映的电影3. 展现行将上映的电影4. 搜寻5. 展现影院6. 我的页面7. 电影详情
我的项目开发环境
编译工具:vscode操作系统:win10node环境:node 12.18.3 npm6.14.6Vue脚手架:vue-cli 4.5.4版本管理工具:git bash 2.28.0服务器软件:Tomcat9.0(我设置Tomcat服务器对应的地址为:localhost:8082)
我的项目开发流程
1. 我的项目需要剖析2. 我的项目工期评估3. 我的项目责任划分 前端: 动态页面制作 前端框架选型 前端页面架构 后端: 数据库开发 API接口文档 API接口实现
创立我的项目
在对应的我的项目目录下关上cmd利用Vue-cli创立我的项目:(我抉择的是Vue3.x版本)vue create 我的项目名创立完后会生成一堆文件夹和文件:
在gitee创立我的项目对应的近程仓库
将本地库与近程库进行关联
把master分支中初始的我的项目文件/目录都推送到近程仓库中
创立并切换到dev分支,把dev分支的初始我的项目文件/目录也推送到近程仓库
创立并切换到一个新的分支(createComponents)用来专门创立组件
以下局部在createComponents分支上开发↓↓↓↓↓↓
初始化路由的配置---电影页面,影院页面,我的页面
总共有三个页面:电影页面,影院页面,我的页面电影页面的路由配置:
影院页面的路由配置:
我的页面的路由配置:
在路由主配置页面(index.js)中引入各路由:
路由重定向的配置
当跳转的路由不存在,利用重定向默认跳转到电影页面(门路:/movie)重定向:redirect:'跳转的路由'在router文件夹下的index.js进行配置:
对我的项目中初始的index.html文件进行一些批改
//减少了user-scalable=no,不容许用户放大放大页面<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"> //引入公共的css款式<link rel="stylesheet" href="<%= BASE_URL %>css/common.css"> //引入图标<link rel="stylesheet" href="https://at.alicdn.com/t/font_2446917_rga2fsr9ns.css">
App.vue文件的批改
留出一个路由进口:<router-view />加上keep-alive标签:实现页面缓存作用,因为切换组件被从新渲染时会影响性能,会显著进步用户体验(会缓存不流动的组件)
创立头部组件
在components文件夹下创立一个header文件夹,并在此文件夹下创立index.vue文件1. 编写相干的HTML,CSS代码2. 为实现动静值(对应页面对应题目)的切换(实现父子组件的数据传递),可利用在Vue中的props(数据单向传递。父组件值的会扭转子组件的值,子组件的值扭转不会影响父组件) 定义一个名称title,类型为String,默认值为'蜘蛛电影' 而后在对应标签(<h1></h1>)中的内容处写上{{title}},接管传递过去的数据
创立尾部组件
在components文件夹下创立一个footer文件夹,并在此文件夹下创立index.vue文件编写相应的HTML,CSS代码
创立页面组件---电影页面
在views文件夹下创立一个movie文件夹,并在此文件夹下创立index.vue文件1. 初始化页面代码2. 在script标签中引入头部组件和尾部组件 import Header from "@/components/header"; import Footer from "@/components/footer";3. 为切换头部组件中的题目,在Header标签中增加属性title,值为'蜘蛛电影',传递给header组件4. 编写相应的HTML,CSS代码 HTML中分为两局部: 1) 电影菜单栏(城市定位,正在热映,行将上映,搜寻) 2) 正在上映和行将上映的电影页面展现(通过router-view标签进行相应的渲染) 5. 对电影菜单栏的每一个性能都应用router-link标签,使其跳转到对应的子路由
配置电影页面中的子路由
电影页面中的子路由有:'city'(城市),'showing'(正在热映),'coming'(行将上映),'search'(搜寻)利用children来进行配置子路由(会拼接到/movie前面)当在电影页面时,默认显示正在热映的页面,即路由重定向到'/movie/showing'
电影页面---创立城市的组件
在components文件夹下创立一个city文件夹,并在此文件夹下创立index.vue文件1. 编写相应的HTML,CSS代码 HTML中分为三局部: 1) 热门城市 2) 城市分类 3) 首字母侧边栏
电影页面---创立正在热映的组件
在components文件夹下创立一个showing文件夹,并在此文件夹下创立index.vue文件1. 编写相应的HTML,CSS代码 HTML中分为每一部电影的区域 而每一个电影区域中分为三局部: 1) 电影图片 2) 电影信息:电影名,电影分数,主演,影院场次 3) 购票按钮
电影页面---创立行将上映的组件
在components文件夹下创立一个coming文件夹,并在此文件夹下创立index.vue文件1. 编写相应的HTML,CSS代码 HTML中分为每一部电影的区域 而电影的每一个区域中分为三局部: 1) 电影图片 2) 电影信息:电影名,想观看人数,导演,主演,上映工夫 3) 预售按钮
电影页面---创立搜寻的组件
在components文件夹下创立一个search文件夹,并在此文件夹下创立index.vue文件1. 编写相应的HTML,CSS代码 HTML中分为两局部: 1) 搜寻输入框 2) 搜寻后果展现区域:大类型,每一部电影对应的信息(电影图片,电影名,电影分数,电影英文名,电影类型,电影日期)
创立页面组件---影院页面
在views文件夹下创立一个cinema文件夹,并在此文件夹下创立index.vue文件1. 初始化页面代码2. 在script标签中引入头部组件和尾部组件 import Header from "@/components/header"; import Footer from "@/components/footer";3. 为切换头部组件中的题目,在Header标签中增加属性title,值为'蜘蛛影院',传递给header组件4. 编写相应的HTML,CSS代码 HTML中分为两局部: 1) 影院菜单栏(全城,品牌,特色) 2) 影院页面展现(通过router-view标签进行相应的渲染)
影院页面---创立展现影院的组件
在components文件夹下创立一个cinemalist文件夹,并在此文件夹下创立index.vue文件1. 编写相应的HTML,CSS代码 HTML中分为每一个影院的区域 而每一个影院区域分为3局部: 1) 影院名和价格 2) 地址和间隔 3) 一些折扣卡之类的
创立页面组件---我的页面
在views文件夹下创立一个mine文件夹,并在此文件夹下创立index.vue文件1. 初始化页面代码2. 在script标签中引入头部组件和尾部组件 import Header from "@/components/header"; import Footer from "@/components/footer";3. 为切换头部组件中的题目,在Header标签中增加属性title,值为'我的蜘蛛',传递给header组件4. 编写相应的HTML,CSS代码 HTML中就渲染一个登录页面的组件
我的页面---创立登录组件
在components文件夹下创立一个login文件夹,并在此文件夹下创立index.vue文件1. 编写相应的HTML,CSS代码 HTML中分为五个局部 1) 账户名输入框 2) 明码 3) 验证码 4) 登录按钮 5) 找回明码和立刻注册
到目前为止,在createComponents分支上的开发大略已实现了,能够把此分支上的货色合并到dev分支上,再推送到近程仓库中
1. 在createComponents分支:git add .,git commit提交代码到本地库2. 切换到dev分支:git checkout dev3. 合并到dev分支上:git merge createComponents --no-ff4. 推送代码到gitee的近程库中:git push origin dev5. 能够删除createComponents分支:git branch -d createComponents
接下来可持续进行相应的开发了
创立新分支setData,专门用来渲染数据的
创立并切换分支setData:git checkout -b setData
以下操作均在setData分支上开发↓↓↓↓↓↓
我把相干数据的api文件都放在Tomcat搭建的服务器上,因为数据寄存的ip地址为localhost:8082,而我的项目运行的ip地址为localhost:8081
所以在渲染数据的时候就存在一个跨域问题
解决跨域问题
在我的项目目录中新建文件:vue.config.js编写:(编写完后记得重启我的项目,才会失效)
渲染数据时应用axios来进行一个ajax的申请
1. 装置axios:npm i -S axios2. 引入axios: 在main.js文件中编写import axios from 'axios'3. 把axios增加在Vue的原型上,在开发中就能利用this间接调用axios: createApp(App).config.globalProperties.$axios=axios;4. 应用axios:(利用getCurrentInstance办法的ctx来调用挂载的axiox) import { getCurrentInstance } from "vue"; const { ctx } = getCurrentInstance(); ctx.$axios.xxx
城市组件---渲染城市数据
局部城市数据:
1. 在data(){return {}}中定义两个数据:hotlist数组(接管传递过去的热门城市数据),citylist数组(接管传递过去的一般城市数据)
2. 在city组件中,在生命周期为mounted的钩子函数中,利用axios的get申请获得城市数据
3. 随后将数据渲染到页面上(利用v-for)
4. 在methods中编写一个办法,使得点击侧边栏字母能跳转到对应首字母的城市列表,并且对应点击的字母背景色变为灰色(在侧边栏字母对应的li上增加一个touchstart事件监听,此办法为handleToIndex) handleToIndex办法思路: 1) 先在类为city_sort的div上增加ref属性,属性值设为city_sort,便于在js中获取到此元素 2) 利用this.$refs.xxx(属性值)来获取到此div元素 3) 依据上一步获取到的div元素来获得它的子元素h2(即取到首字母的区域) 4) 利用offsetTop办法来取得每一个首字母达到顶部的间隔 5) 对城市列表的包裹层(即类为city_list的div,这里示意的是第二步失去div的父节点)用scrollTop的办法来扭转到顶部滚动的间隔,值为第四步失去的间隔值 6) 而后是扭转点击侧边栏字母里的每一项的背景色彩 7) 在类为city_index的div上增加ref属性,属性值设为city_index 8) 利用this.$refs.xxx(属性值)来获取到此div元素 9) 依据上一步获取到的div元素来获得它的子元素li(即每一个字母项) 10) 先利用for循环把全副li的背景色彩变为通明色 11) 再对点击的li扭转背景色为灰色(利用xxx.style.background='xxxx')
正在热映组件---渲染正在热映的电影数据
局部正在热映的电影数据:
1. 在data(){return {}}中定义一个数据:movielist数组(接管传递过去的正在热映的电影数据)
2. 在showing组件中,在生命周期为mounted的钩子函数中,利用axios的get申请获得正在热映的电影数据
3. 随后将数据渲染到页面上(利用v-for) 其中传递过去的图片门路须要通过一些宽高设置的解决(应用Vue3.x的过滤办法(在main.js文件编写)) 还有显示怎么版本的图片标识可用v-if来进行判断
行将上映组件---渲染行将上映的电影数据
局部行将上映的电影数据:
1. 在data(){return {}}中定义一个数据:cominglist数组(接管传递过去的行将上映的电影数据)
2. 在coming组件中,在生命周期为mounted的钩子函数中,利用axios的get申请获得行将上映的电影数据
3. 随后将数据渲染到页面上(利用v-for) 其中传递过去的图片门路须要通过一些宽高设置的解决(应用Vue3.x的过滤办法(在main.js文件编写)) 还有显示怎么版本的图片标识可用v-if来进行判断
搜寻组件---渲染搜寻后果的数据
局部搜寻后果的电影数据:(这里只提供了无关字母a,b,aaa的数据)
1. 在data(){return {}}中定义一个数据:message字符串(输入框的值),movielist数组(接管传递过去的电影数据)
2. 在search组件中,在watch的钩子函数中,若message发生变化,则利用axios的get申请获得搜寻失去的电影数据(在watch中,可做函数节流,Ajax异步数据获取,操作DOM;依赖固定的数据类型等。一个本来就存在的数据,发生变化就执行函数) 1) 在input标签中,利用v-model双向绑定message数据,监听输入框的值 2) 在监听message中进行axios的get申请
3. 随后将数据渲染到页面上(利用v-for) 其中传递过去的图片门路须要通过一些宽高设置的解决(应用Vue3.x的过滤办法(在main.js文件编写))
4. 在输入框输出数据的这种实时监测数据的状况下,只有最初一次确定的后果,后面的都革除掉。(即在这期间axios会触发屡次申请,要把没用到的申请中断掉)这个时候就要应用函数防抖的一个伎俩:1. 可应用定时器的形式2. 也可利用axios终止申请的一些办法 1) 一开始可先判断终止申请的函数是否曾经存在了,若存在就终止 2) 在axios的第二个参数中新建一个cancelToken的实例(利用axios的构造函数CancelToken)(使得申请具备能够勾销的性能)
cinemalist组件---渲染影院的数据
局部影院的数据:(这里只提供了江门,成都的影院数据)
1. 在data(){return {}}中定义一个数据:cinemalist数组(接管传递过去的影院数据)
2. 在cinemalist组件中,在生命周期为mounted的钩子函数中,利用axios的get申请获得影院的数据
3. 随后将数据渲染到页面上(利用v-for) 还有显示怎么小卡片可用v-if来进行判断
4. 在前面的步骤,会实现依据不同的城市地区渲染不同地区的影院数据
到目前为止,在setData分支上的开发大略已实现了,能够把此分支上的货色合并到dev分支上,再推送到近程仓库中
1. 在setData分支:git add .,git commit提交代码到本地库2. 切换到dev分支:git checkout dev3. 合并到dev分支上:git merge setData --no-ff4. 推送代码到gitee的近程库中:git push origin dev5. 能够删除setData分支:git branch -d setData
接下来可持续进行相应的开发了
创立新分支getCity,专门用来城市关联数据的性能(不同城市关联不同的影院数据)
创立并切换分支getCity:git checkout -b getCity
以下操作均在getCity分支上开发↓↓↓↓↓↓
全局封装berrter-scroll组件
作用:1. 使得滚动起来顺滑,没有那么僵硬2. 解决滑动时不会触发点击事件(实现tap事件的一种办法,还有能够利用zepto,vue-touch来实现)组件失效的前提:1. 包裹容器的高度或宽度必须小于内容的高度和宽度2. 要等所要触发的内容都渲染完步骤:1. 先装置better-scroll插件:npm i -S better-scroll2. 在components文件夹下创立一个scroller文件夹,并在此文件夹下创立index.vue文件3. 编写HTML,CSS局部 HTML局部是有一个包裹层wrapper,外面是一个slot插槽(显示对应HTML模块)4. 引入better-scroll插件:import BScroll from "better-scroll";5. 在钩子函数mounted中编写: 1) 新建一个better-scroll实例:this.scroll = new BScroll('对应的包裹层元素',{相干的一些配置}) 2) 实现上拉刷新,须要绑定一个scroll事件:this.scroll.on("scroll", (pos) => {}) 在scroll事件中执行实现上拉刷新的办法(利用props接管由父组件传过来的办法):handleToScroll(){} 还要绑定一个touchend事件(滑动完结会触发),来表明加载胜利:this.scroll.on("touchEnd", (pos) => {}) 在touchEnd事件中执行绝对应的办法(利用props接管由父组件传过来的办法):handleToTouchEnd(){}; 以上的这些都要在内容都加载完后才触发,所以须要用到vue中的.$nextTick(()=>{}),mounted中的内容都增加到这外面的函数中执行6. 在钩子函数updated中编写: this.scroll.refresh(); //当数据更新时从新计算滑动值7. 而在city组件中用到此滑动组件时,会发现侧边栏字母无法控制对应字母区域的跳转 因为此时better-scroll在管制着这一块区域,对应的办法就无奈失效了 所以要利用better-scroll中的办法(scrollTo(x,y)),在better-scroll中增加此办法:toScrollTop(y) {this.scroll.scrollTo(0, y);} 随后在city组件中调用该办法 1) 在scroller元素上增加ref属性,属性值为city_list 2) 通过获取到这个元素来调用其身上的办法8. 全局注册此组件,使得能够在文件中随时应用。在main.js文件中编写:
better-scroll组件全局的编写:
better-scroll组件的调用:
全局封装loading组件
因为有些内容都要通过申请加载进去,在期待数据响应的过程中,能够在加载的过程中增加一个loading组件,看上去也会更好看一点,用户的体验感也会更好1. 在components文件夹下创立一个loading文件夹,并在此文件夹下创立index.vue文件2. 编写HTML,CSS局部 (可本人写,也可间接去找一些css3实现loading成果的组件,举荐网址:https://codepen.io/trending)3. 全局注册此组件,使得能够在文件中随时应用。在main.js文件中编写:
loading组件全局的编写:
loading组件的调用:(可在data中定义一个Boolean类型的数据:isLoading,为true就显示loading组件,否则就显示better-scroll组件)
设置城市数据的本地存储与状态治理
对于一些不怎么变动的数据,能够存储到本地(如:localStorage)城市数据的本地存储:(利用localStorage)1. 当通过ajax申请失去的数据后,利用window.localStorage.stetItem('xx',xx)来存储数据(留神要先用JSON.stringfy办法来变为字符串再寄存)2. 在ajax申请前,能够先做一个判断,若本地存储中有相干数据,则间接进行赋值(留神取出数据时先要用JSON.parse办法来变为JSON对象再赋值),否则就进行ajax申请获得数据
城市数据的状态治理:(这里就要用到store文件夹下的货色)1. 先在store文件夹下新建一个名为city的文件夹,在city文件夹下新建一个index.js文件(专门用来对城市数据进行状态治理)2. 在store的index.js文件中,引入下面的city模块文件:import city from './city'3. 把下面引入的city子模块增加到modules中4. 在city文件中的配置:(每个子模块都有本人的state、mutation、action等办法) 1) 在state中定义两个变量:nm(城市名),id(城市id) 2) 在mutation中定义一个办法用来接管传递过去的值并更新state状态里的值: CITY_INFO(state,payload){ state.nm=payload.nm; state.id=payload.id; } 3) exports default{}的配置: export default { namespaced:true, //使其成为带命名空间的模块。保障在变量名一样的时候,增加一个父级名拼接(在应用模块中的mutations、getters、actions和获取属性时,要加上模块名) state, actions, mutations }
5. 在电影组件(movie)的城市标签显示中,获取到store状态里的city模块的城市名来实现动态显示城市数据(获取对应的属性值:$store.state.模块名.模块属性)
6. 在city组件中,实现点击每一个城市就会更新以后的城市状态信息并存储起来 1) 为每个城市li绑定click事件,并执行handleToCity()办法 2) 在handleToCity办法中: 通过this.$store.commit("模块名/模块中的mutations", {对应的值})办法把接管到对应的城市名和城市id都传给city的状态治理并更新 利用localStorage存储以后状态的城市名和城市id 抉择完城市后,利用this.$router.push('路由门路')来主动跳转到正在上映的电影页面
通过以后城市的id关联渲染相干的行将上映的电影数据和影院数据
这里渲染的数据只提供了成都和江门地区要想抉择完对应的城市后从新渲染相干的数据,无非就是从新发动ajax申请接收数据但在生命周期mounted中,一旦有缓存零碎keep-alive存在,那么再次申请是不会进行触发了所以就要在actived生命周期中进行相干的申请(activated生命周期是在keep-alive组件激活时调用的)惯例来说,是应该在activated生命周期中执行的,但我这里反而要在mounted生命周期中执行才失效(目前我也不太分明这个起因,好奇怪)渲染对应城市的行将上映的电影数据和影院数据的一些步骤:1. 如果没有切换城市的话,咱们则无需发送ajax申请 1) 在data中新定义一个数据prevCityId(示意上一次抉择的城市id),一开始赋值为-1 2) 通过this.$store.state办法来获取到城市状态治理中的城市id 3) 把prevCityId与获取到以后状态的城市id作比拟,若相等(即没有切换城市),则间接return退出,不须要发送申请,间接渲染缓存的数据2. 若切换了城市,要发送申请,则要在申请的地址拼接上以后状态的城市id进行申请数据,并且要把以后状态的城市id赋值给prevCityId
全局封装弹窗组件
若利用vue来创立这个组件,在传参数或者复用的时候会有点麻烦,所以咱们这里能够利用JS来封装此组件,并接管对应的参数1. 在components文件夹下创立一个名为JS的文件夹,在JS文件夹下创立一个index.js文件(作为JS主模块文件),在JS文件下创立一个名为msgBox的文件夹,在msgBox文件夹下创立一个index.vue2. 在msgBox对应的index.vue中编弹窗的HTML,CSS局部3. 编写JS对应的index.js文件 1) 引入vue对应的createApp和h函数:import { createApp,h } from 'vue' 2) 引入方才编写的msgBox vue组件:import msgBox from './msgBox' 3) 定义导出一个名为messageBox的闭包函数,为引入此组件提供一个接口:export var messageBox=(function(){})() 4) 在此闭包函数中,首先定义一个默认配置的变量:defaults 5) 接下来就是编写返回进来的一个函数 6) 接管传过来的配置参数,并笼罩掉默认的参数 7) 定义对应的动静组件并挂载到DOM上(Vue2.0中能够用Vue.extend({})办法,Vue3.0中能够用createApp({})办法) i) 利用createApp定义一个名为app的实例:const app=createApp({}) ii) 利用render(){return h()}来进行渲染组件及相干的props属性和插槽属性等 (h返回一个"虚构节点",蕴含向 Vue 形容它应在页面上渲染哪种节点的信息,包含所有子节点的形容。共接管三个参数:1. HTML 标签名、组件或异步组件。应用返回 null 的函数将渲染一个正文(必选),2. 一个对象,与咱们将在模板中应用的 attribute、prop 和事件绝对应(可选),3. 子代 VNode,应用h()生成,或者应用字符串来获取“文本 VNode”,或带有插槽的对象(可选)) iii) 新创建一个div节点,将此组件增加到body,并挂载
4. 而后持续编写msgBox对应的index.vue文件 要接管传过来的插槽属性值,可利用v-slot和slot的配合 要接管props的值,先在props:{}中定义那两个函数值,通过this.$props.xxx来调用对应的函数办法
这里是对于弹窗的一下小改良:1. 在cancel和ok对应的区域中,判断哪个有值就显示哪个区域(利用v-if)2. 点击ok区域后也要移除掉弹窗并解除绑定3. cancel和ok值都当做props属性传进去,并在对应的msgBox vue组件中进行接管
实现城市定位
城市的定位是在movie组件(电影页面)中进行的实现城市定位的办法是通过高德地图凋谢的API实现的(详情可查看网址:https://blog.csdn.net/qq_42817227/article/details/98303058?ops_request_misc=%7B%22request%5Fid%22%3A%22161728232116780357267112%22%2C%22scm%22%3A%2220140713.130102334..%22%7D&request_id=161728232116780357267112&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-98303058.first_rank_v2_pc_rank_v29&utm_term=应用高德地图定位)1. 在movie组件中,先引入弹窗组件:import { messageBox } from "@/components/JS";2. 在methods中定义一个办法handleOk(实现定位的办法),编写此办法的前提是须要在public文件夹中的index.html中引入对应的js链接 handleOk的函数办法: 1) 编写对应提供的定位函数办法 2) 在胜利获取到的函数办法中,把定位失去的城市名和城市id都存储在localStorage中,同时利用this.$store.commit()办法更新城市的以后状态 3. 在生命周期mounted中,先执行handleOk办法进行定位,再判断以后的城市状态和以后定位的城市是否相等,如果不相等,则弹出弹窗提醒切换定位(2s后再弹出) 弹窗的参数值: messageBox({ title: "定位", content: this.nowCityName, cancel: "勾销", ok: "切换定位", handleOk: () => { this.handleOk(); window.location.reload(); }, }); 4. 在生命周期updated中,数据更新了就从新判断一下以后的城市状态和以后定位的城市是否相等,看是否须要从新定位
到目前为止,在getCity分支上的开发大略已实现了,能够把此分支上的货色合并到dev分支上,再推送到近程仓库中
1. 在getCity分支:git add .,git commit提交代码到本地库2. 切换到dev分支:git checkout dev3. 合并到dev分支上:git merge getCity --no-ff4. 推送代码到gitee的近程库中:git push origin dev5. 能够删除getCity分支:git branch -d getCity
接下来可持续进行相应的开发了
创立新分支detailPage,专门开发电影详情页面
创立并切换分支detailPage:git checkout -b detailPage
以下操作均在detailPage分支上开发↓↓↓↓↓↓
创立组件---电影详情页面组件
1. 电影详情页面的渲染入口:电影详情页面的组件渲染,能够通过在movie组件中通过router-view命令视图来渲染进去但这样一来,就会和之前写的渲染正在上映和行将上映的组件的router-view产生抵触了,这个时候咱们能够通过name来把它们辨别开来(即命名视图),导致不让它们渲染凌乱咱们把渲染电影详情组件的命令视图的name设为detail
2. 接下来就要在movie的路由中设置详情页的路由因为应用了命名视图,所以在对应子路由渲染组件的时候,写法也会略微不一样而且可通过路由传参的形式把在电影页面失去的电影id值传给电影详情页面,电影详情页通过props接管传过来的id值,可申请到对应的电影详情数据并渲染进去以下图片是相干的路由配置
3. 编写电影详情页的组件 1) 在views文件夹下的movie文件夹中,新建一个名为detail.vue的文件 2) 编写相干的HTML,CSS 引入header组件,因为要在头部的左侧加上一个回退上一级性能,所以须要减少一个图标,在header组件中新减少一个插槽用来渲染图标
3) 定义props属性来接管从电影页面传过来的电影id(路由中定义的属性名是什么,这里的props属性名就定义什么) 4) 定义一个handleToBack办法实现返回上一级路由,利用 this.$router.back()办法来实现 5) 而后就是利用ajax申请接收数据了,通过和接管到的电影id配合,来获得相应的电影详情数据 6) 其中在演职人员的展现中,咱们能够利用swiper插件来实现挪动端的滑动展现(要引入swiper相干的CSS,JS文件) (swiper中文网:https://www.swiper.com.cn/)
到目前为止,在detailPage分支上的开发大略已实现了,能够把此分支上的货色合并到dev分支上,再推送到近程仓库中
1. 在detailPage分支:git add .,git commit提交代码到本地库2. 切换到dev分支:git checkout dev3. 合并到dev分支上:git merge detailPage --no-ff4. 推送代码到gitee的近程库中:git push origin dev5. 能够删除detailPage分支:git branch -d detailPage
以上根本就是客户端的一些开发了,你也能够自行欠缺一些其余的性能
也能够进行一下真机测试,即在手机上浏览开发的这个我的项目
进行真机测试的前提,就是手机和电脑要连贯到同一个网络查看运行我的项目时的Network的地址,间接在手机浏览器中输出这个地址就能够查看了
若你这里显示的Network地址为unavailable解决办法:在vue.config.js文件中,增加一个public属性,属性值为此网络的IPv4地址,并加上相应的端口号,重启我的项目,就有显示啦
我的项目的一些优化
1. 能够在此我的项目开始的时候,加一个期待加载的动画(在index.html文件中增加)2. 批改根底的公共根门路(能够指定一个根目录,在此目录下拜访所有的文件,组件) 利用publicPath来批改生产模式和开发模式的根底公共根门路(在vue.config.js文件下配置) 这是我的配置批改:
我的项目的打包
我的项目打包命令:npm run build打包后的文件放在dist目录中
上面是后端的操作↓↓↓↓↓↓
咱们的后端开发须要用到的技术
1. Node.js2. Express3. MongoDB4. 其余模块
后端开发的前提筹备
为实现对于我的页面的对应性能,须要进行后盾治理的开发,利用数据库存储用户的对应信息装置node (可查看我的另一篇文章:对于node)装置express:npm i -s express可全局装置express-generator:npm install -g express-generator(express-generator会疾速创立应用程序框架)在我的项目目录spider的同级目录下,关上cmd输出命令:express -e 服务框架名
而后就会生成对应的一个目录
进入此目录,关上package.config文件,如果你想实时批改(监听)文件可把scripts中的"start": "node ./bin/www"改为"start": "nodemon ./bin/www"(前提是要装置nodemon的这个插件)运行后,在浏览器输出对应的地址(我这里设置的端口是3000),若呈现下图的内容,则证实曾经关上胜利
因为咱们要用到数据库来存储咱们的用户数据,咱们这里就应用MongoDB数据库咱们能够装置mongoose模块,利用express来对其操作数据装置mongoose:npm i -S mongoose而后在spiderserver目录下新建一个名为db的文件夹,用来寄存数据库的数据关上数据库:(若你曾经配置了mongodb的全局门路,可在任意一处输出命令。若没有,则要在对应的mongodb的bin目录下关上cmd输出命令)输出命令:mongod --dbpath=db文件夹的门路咱们能够新建一个名为untils的文件夹,在此文件夹下新建一个名为config.js的文件,这个文件是专门用来编写数据库和一些模块的相干配置编写config.js文件:
而后再app.js文件中引入刚编写的mongoose模块文件:var {Mongoose}=require('./untils/config');并调用它的连贯数据库办法:Mongoose.connect();随后可通过命令行或者可视化的数据库工具Robo 3T来创立咱们对应的数据库(具体操作可查看我的另一篇文章《对于MongoDB》)我这里就应用可视化的数据库工具来创立
创立实现后,咱们就能够再次启动咱们的服务器,看数据库是否连贯胜利,若呈现如下图的状况,则示意已连贯胜利
对于我的页面须要编写的相干接口
1. login:登陆接口2. register:注册接口3. logout:登出借口4. verify:验证接口5. getUser:获取用户信息的接口6. findPassword:找回明码的接口...因为后端采纳的是MVC框架,咱们须要把数据和控制器分离出来,咱们能够在此目录下新建对应的文件夹models和controllers来别离解决相干的货色和编写相干的接口controllers是用来编写相干的解决办法models是用来治理相干的数据库数据在这两个文件夹下别离新建文件users.js
编写我的页面的接口---验证接口verify
咱们这里的验证接口是通过邮箱发送验证码验证(会应用到nodemailer模块)筹备一个发验证码的邮箱(开明SMTP服务)和一个接管验证码的邮箱在untils文件夹下的config.js文件中编写发送邮箱验证码的配置(先引入nodemailer模块):
在controllers文件夹下的users.js文件中先引入untils下的users.js模块的Email对象,再编写verify接口的解决办法:
在routers文件夹下的index.js文件中先引入controllers文件模块,调用其verify接口的解决办法,而后配置verify接口的路由:(get申请)
设置验证码的时效性:1. 在spiderserver/config/untils下的Email对象中新增一个获取以后工夫的办法
2. 在spiderserver/controllers/users.js下的验证接口解决办法中,把发送验证码的工夫存入session中
3. 在spiderserver/controllers/users.js下的注册接口解决办法中,用以后的工夫减掉方才存入session中的发送验证码的工夫,判断有没有超过60秒,若超过60s则证实验证码已过期
编写我的页面的接口---注册接口register
为了能在注册的时候拿到验证时的验证码,须要对数据进行长久化操作,存入session中(利用express的中间件express-session)装置express-session:npm i -S express-session在app.js文件中引入express-session模块:var session=require('express-session');引入模块后可进行相干的配置:(记住要在路由申明前进行配置)
在验证接口中把接管邮箱和验证码都存入session中:req.session.verify=verify; req.session.email=email; 因为用户的注册信息须要保留到数据库中,所以在models/users.js下进行相干的编写:1. 定义注册接口的数据库骨架2. 定义对应的数据库模型(留神让惟一值失效的做法)3. 定义一个数据保留的办法
随后在controllers/users.js下编写注册接口的解决办法:1. 引入刚定义的数据库模型2. 获取到用户进行post申请的注册数据3. 判断传进来的邮箱或者验证码是否与session中寄存的相等4. 利用定义的数据保留办法保留相应的用户名,明码,邮箱5. 而后依据保留的后果判断是否注册胜利
在routers文件夹下的index.js文件中配置rigister接口的路由:(post申请)router.post('/register',usersController.register);
编写我的页面的接口---登录接口login
在models/users.js下编写数据库查找数据的办法:
在controllers/users.js下编写注册接口的解决办法:1. 获取到用户进行post申请的登录数据2. 依据用户传过来的登录数据在数据库进行查找匹配3. 而后依据查找的后果判断是否登录胜利,若登录胜利则把username存入session中
在routers文件夹下的index.js文件中配置login接口的路由:(post申请)router.post('/login',usersController.login);
编写我的页面的接口---登出的接口logout
在controllers/users.js下编写登出的解决办法:间接把存储在session的用户名变为空
在routers文件夹下的index.js文件中配置logout接口的路由:(get申请)router.get('/logout',usersController.logout);
编写我的页面的接口---获取用户信息的接口getUser
在controllers/users.js下编写获取用户信息的解决办法:判断session中的username是否为空,不为空则获取胜利并把相应的用户数据寄存到session中,否则获取失败
在routers文件夹下的index.js文件中配置getUser接口的路由:(get申请)router.get('/getUser',usersController.getUser);
编写我的页面的接口---找回明码的接口findPassword
在models/users.js下编写更新数据库数据的办法:(依据传过来的对应邮箱进行更新)
在controllers/users.js下编写找回明码的解决办法:1. 获取到用户进行post申请的相干数据2. 判断传过来的邮箱和验证码是否和session存储的一样3. 若一样,则调用usreModel下的updatePassword办法对明码进行批改,否则失败
截止目前,无关我的页面的用户接口曾经写完了
接下来持续开发我的页面的组件↓↓↓↓↓↓
配置我的页面的子路由
在src/router/mine/index.js中配置我的页面相干的子路由(包含登录组件,集体核心组件,注册组件,找回明码组件)当显示我的页面时,重定向路由到集体核心页面
欠缺之前创立的登录组件的性能
1. 在data中定义两个数据:username(用户名),password(明码)2. 对用户名的输入框和明码的输入框都利用v-model别离对username,password数据进行双向绑定3. 给登录按钮增加一个touchstart事件,执行handleToLogin办法4. 编写handleToLogin办法: 1) 向之前编写的登录login接口进行ajax申请(记得先进行对应的反向代理,要不然会呈现跨域无法访问的问题,反向代理时本地编写的接口最好放在后面,免得有些不必要的谬误) 2) 依据status来判断是否登录胜利(登录胜利则跳转到集体核心的页面) 3) 引入弹窗组件,利用弹窗组件对其进行一个反馈信息的作用
设置用户的一些状态治理
在store文件夹下新建一个名为user的文件夹,在此文件夹下新建一个index.js文件并编写。随后在store/index.js中引入该文件模块
创立我的页面的相干组件---集体核心组件
1. 在views/mine下新建一个名为center.vue的文件2. 编写相应的HTML,CSS HTML局部中,以后用户名通过$stor.state.xxx.xxx显示进去
3. 对退出按钮增加一个touchstart事件,并编写handleToLogout办法:4. 通过对logout接口进行ajax申请,通过status判断是否登出胜利,登出胜利则跳转到登录页面并更新用户状态治理的用户名为空
5. 在进入集体核心页背后能够先利用"导航守卫"判断一下以后用户的登录状态再决定是否能够进入此组件(用户的登录状态可利用向getUser接口发动申请来判断) 若此时用户为登录状态则能够进入集体核心页面并更新用户状态治理的用户名为以后用户的用户名,反之则跳转到登录页面
创立我的页面的相干组件---注册组件
1. 在components新建一个名为register的文件夹,在此文件夹下新建一个index.vue文件2. 编写相应的HTML,CSS
3. 在data中定义六个数据:username(用户名),password(明码),email(邮箱),verify(验证码),verifyInfo(验证码的相干信息),disabled(判断按钮是否禁用状态)4. 对用户名的输入框,明码的输入框,邮箱的输入框和验证码的输入框都利用v-model别离对username,password,email,verify数据进行双向绑定5. 引入弹窗组件,利用弹窗组件对其进行一个反馈信息的作用6. 对发送验证码的按钮增加一个touchstart事件,并编写handleToVerify办法:(利用ajax对verify接口进行申请) 点击确定后触发countDown办法
7. 对注册的按钮增加一个touchstart事件,并编写handleToRegister办法:(利用ajax对register接口进行申请)
创立我的页面的相干组件---批改明码组件
1. 在components新建一个名为findPassword的文件夹,在此文件夹下新建一个index.vue文件2. 编写相应的HTML,CSS
3. 在data中定义三个数据:password(明码),email(邮箱),verify(验证码)4. 对明码的输入框,邮箱的输入框和验证码的输入框都利用v-model别离对password,email,verify数据进行双向绑定5. 引入弹窗组件,利用弹窗组件对其进行一个反馈信息的作用6. 对发送验证码的按钮增加一个touchstart事件,并编写handleToVerify办法:(利用ajax对verify接口进行申请)
7. 对确认批改的按钮增加一个touchstart事件,并编写handleToPassword办法:(利用ajax对findPassword接口进行申请)
接下来是开发后盾治理页面↓↓↓↓↓↓
设置后盾治理的管理员接口与权限
1. 先在spiderserver/models/users.js中的数据库骨架新增一个值为isAdmin,此值为Boolean类型。用于判断是否有管理权限
2. 在spiderserver/contorllers/user.js中,在登录接口的解决办法中,当登陆胜利时,也把其管理权限的值也存入到session中,以便当前判断是否有管理权限。在获取用户信息接口的解决办法中,当获取胜利时,把其管理权限的值存入到data中
3. 在spiderserver/routes下新建一个名为admin.js的文件,配置管理页面的接口路由 1) 先设置一个拦截器,用于判断其用户的管理权限,才可进入治理页面 2) 配置管理页面的主页路由
4. 在spiderserver/app.js中引入该治理页面的路由
后盾治理页面是利用element-ui组件库搭建的
element-ui中武官网:https://element-plus.gitee.io/#/zh-CN1. 装置element-ui插件:npm i -S element-ui2. 在main.js文件中引入element-ui: import ElementPlus from 'element-plus'; import 'element-plus/lib/theme-chalk/index.css'; app.use(ElementPlus);
配置后盾治理页面的路由
在spider/src/router下创立一个名为admin的文件夹,在此文件夹下创立一个index.js文件其子路由包含用户治理页面路由,电影治理页面路由,影院治理页面路由
随后在spider/src/router下的index.js文件下引入该路由文件模块
创立治理后盾组件---主页面组件
1. 在spider/src/views下新建一个名为admin的文件夹,在此文件夹下新建一个index.vue文件2. 编写相应的HTML,CSS(布局为头部,侧边栏,主区域)
3. 在spider/store/user/index.js下,新增用户的一个管理员状态值isAdmin,默认值为false
4. 在集体核心页面依据其是否为管理员渲染用户的身份,若为管理员则增加一个router-link标签来跳转到后盾治理页面 1) 在获取到用户信息后,把用户的管理权限的值更新到用户的状态治理中 2) 登出的时候,用户状态治理中的管理权限的值为false
5. 在治理后盾的主页面中,利用导航守卫来判断以后用户是否有管理权限来进入治理后盾
创立治理后盾组件---用户治理组件
1. 在spider/src/views/admin下新建一个user.vue文件2. 编写相应的HTML,CSS(表格区域分为账号创立日期,用户名,邮箱,操作(未解冻和删除))
3. 在data中定义一个数据:tableData(数组,用于寄存全副的用户信息)4. 在生命周期mounted中利用ajax对用户治理接口发动申请(把失去的全副用户数据都利用tableData数据渲染到页面上)5. 对解冻操作的按钮监听一个click事件,并执行编写的handleToFreeze办法: 1) 传入参数(利用scope上的属性:scope.$index, scope.row) 2) 利用ajax对解冻账号操作的接口发动申请,依据status的值判断解冻操作是否胜利,利用element-ui的信息弹窗组件来反馈信息(若解冻操作胜利,则把对应的isFreeze值取反即可) 6. 对删除操作的按钮监听一个click事件,并执行编写的handleToDelete办法: 1) 传入参数(利用scope上的属性:scope.$index, scope.row) 2) 利用ajax对删除账号操作的接口发动申请,依据status的值判断删除操作是否胜利,利用element-ui的信息弹窗组件来反馈信息(若删除操作胜利,则利用splice办法把对应的tableData指定的index项删除掉)
7. 对于解冻的账号,登录时应提醒账号已解冻,登录失败 在spiderserver/controllers/users.js下编写一些相应判断
在login组件中也要在弹窗中反馈对应的信息
8. element-ui对数据进行分页解决 1) 引入分页组件
2) 在data中定义两个数据:currentPage(当前页),pageSize(每页显示的数据) 3) 通过computed依据当前页和每页显示的数据来计算nowTableData的每一页渲染的数据,此时table应该是渲染nowTableData的数据
4) 编写handleCurrentChange办法来扭转当前页的值
创立治理后盾的接口---用户治理接口
在用户治理接口中,要实现三个办法:1. 显示所有用户数据的办法 1) 在spiderserver/models/users.js下编写一个返回显示所有用户数据的办法
2) 在spiderserver/controllers/admin.js下编写显示所有用户信息的操作的解决办法(引入models中刚编写的办法)
3) 在spiderserver/routes/admin.js下配置显示用户数据的接口路由:router.get('/userList', adminController.userList);2. 账号解冻操作的办法 1) 在spiderserver/models/users.js的数据库骨架中,新增一个值为isFreeze,此值为Boolean类型。用于判断用户账号是否被解冻
在spiderserver/models/users.js下编写一个数据库更新账号的解冻状态的办法(以邮箱号为标识来更新isFreeze的值)
2) 在spiderserver/controllers/admin.js下编写更新账号的解冻状态操作的解决办法(引入models中刚编写的办法)
3) 在spiderserver/routes/admin.js下配置账号解冻的接口路由:router.post('/updateFreeze', adminController.updateFreeze);3. 账号删除的办法 1) 在spiderserver/models/users.js下编写一个数据库删除用户账号的办法(以邮箱号为标识来删除)
2) 在spiderserver/controllers/admin.js下编写删除用户账号操作的解决办法(引入models中刚编写的办法)
3) 在spiderserver/routes/admin.js下配置账号删除的接口路由:router.post('/deleteUser', adminController.deleteUser);
对于用户头像上传的操作
编写用户头像上传的接口:1. 在spiderserver/models/users.js下的数据库骨架中增加一个值为userHead,类型为String,默认值为http://localhost:3000/images/default.jpg,示意用户的头像
2. 在spiderserver/models/users.js下编写数据库更新用户头像的办法
3. 在spiderserver/untils/config.js下编写用户头像上传的根底公共门路
4. 在spiderserver/controllers/users.js下编写更新用户头像的办法(先引入刚编写的config.js的Head对象,fs模块)
5. 后端上传货色能够利用node中的multer模块(详情用法可参考文档:http://expressjs.com/en/resources/middleware/multer.html) 1) 在spiderserver/routes/users.js下引入multer模块,并指定头像的上传门路
2) 配置上传文件接口的路由
前端的操作:1. 在用户的治理状态中新增一个状态量userHead,初始值为空串
2. 在进入集体核心页背后,若进入胜利,也要更新一下用户头像状态的值
3. 登出页面的时候,把用户头像状态的状态值变为空串
4. 在集体核心页面组件中增加一个区域,是负责上文头像文件的
5. 在上传文件的按钮上绑定一个touchstart事件,执行编写的handleToUpload办法 须要留神的是在调用用户头像上传的这个接口时,要传入文件的相干参数(利用FormData()对象,更多FormData的用法可参考:https://www.cnblogs.com/wssdx/p/11244766.html)和传入"Content-Type"的值是为"multipart/form-data" 更新用户头像的状态值时记得在前面加个随机数来革除缓存
6. 在后盾治理页面中,新增一列来寄存用户上传的头像
我的项目优化---明码加密
加密可应用node中的crypto模块1. 在spiderserver/untils下新建一个base.js,用来编写加密的相干办法 1) 引入crypto模块:const crypto = require('crypto'); 2) 编写一个加密办法setCrypto
2. 在spiderserver/controllers/users.js,先引入下面编写的文件模块,再去设置寄存明码为加密的明码模式 如:
我的项目优化---登录时防攻打验证码
利用node的trek-captcha模块生成图形验证码1. 在spiderserver/untils/base.js下引入trek-captcha模块,再编写图形验证码生成办法
2. 在spiderserver/controllers/users.js,先引入下面编写的文件模块,再去编写生成图形验证码的解决办法
3. 在spiderserver/routes/users.js下配置生成图形验证码的接口路由:
在login组件中应用此组件:1. HTML中新减少一个区域:填写验证码
2. 为img标签绑定一个touchstart事件,执行编写的handleToVerifyImg办法实现点击图片更新验证码
3. 当登陆失败点击确定后,也要从新刷新图片验证码(在img标签增加一个ref属性,属性值为verImg,用于获取到该img元素)
对于我的项目的线上部署
把打包好的我的项目交给后端,后端要选取一个web服务器(http服务器)咱们这次选取的一个web服务器是nginx什么是nginx?为什么要抉择nginx呢?nginx的益处有哪些呢?以上的种种问题可移步至另一篇文章《对于nginx》!!!而上线我的项目,则须要有一个云服务器(对应的域名或一个IP地址),能够去阿里云,腾讯云等看看云服务器都设置好当前,可通过windows的近程连贯来连贯近程服务器,在近程服务器中也装置nginx,配置对应的反向代理截止目前,就能够在浏览器上拜访私有的IP地址,就能够拜访到咱们的这个我的项目了
我的项目过程中遇到的一些问题
1. 在gitee创立近程仓库时没有把readme初始化仓库那一项去掉,导致一开始的近程库不是一个空仓库,所以无奈把本地库中的初始我的项目推送到近程库中,始终卡住 git push时呈现的报错:(大略如下)
解决办法也可参考网址:https://blog.csdn.net/cuomer/article/details/811421592. 在router下的index.js编写路由重定向的时候,若有任意不匹配的路由时,则跳转到电影路由 我原本写的path值为'/*'来示意任意不匹配的路由,之前都是能够失效的,但这次做我的项目的时候不行 所以我在网上找了一下解决的计划,把path的值改为'/:catchAll(.*)'就能够了 3. 在解决跨域问题,编写vue.config.js文件时,输出模块我写成了export default{}模式,后果从新运行我的项目时报错了,可能我没有新减少一些模块来反对这种es6的写法,所以改成了module.exports={}的模式 require: node 和 es6 都反对的引入(CommonJS标准) export / import / export default: 只有es6 反对的导出引入 module.exports / exports: 只有 node 反对的导出(CommonJS标准) 4. Vue3.x挂载全局及调用挂载上的办法 在以前是能够间接应用以下办法来进行全局的挂载 import Vue from 'vue' Vue.prototype.xxx=xxx; 在我想要全局挂载axios的时候,就利用了下面那个办法,报错了 我上网搜了一下,发现Vue3.x中Vue不能间接这样挂载全局,上面是挂载的办法: import { createApp } from 'vue' import App from './App.vue' createApp(App).config.globalProperties.$xxx=xxx; 调用全局挂载里的办法:this.$xxx 5. 对于Vue3.x的过滤器定义和应用 在Vue2.x的时候,定义过滤器: import Vue from 'vue' Vue.filter('过滤办法名',(xx)=>{ return xxx; }) 应用的时候xx | 过滤办法名(xx) 在我渲染正在热映的组件时,想要设置一个过滤器来扭转传过来的图片的宽高,应用了下面的办法后果就报错了 原来在Vue3.x中,这个办法曾经破除掉了 上面是Vue3.x中用的办法: 定义一个过滤办法,挂载到全局上: import { createApp } from 'vue' import App from './App.vue' createApp(App).config.globalProperties.$filters = { 过滤办法名(xx) { return xxx; } } 应用时:$filters.过滤办法名(xx) 6. computed和watch的区别: 详情可参考网址:https://blog.csdn.net/weixin_42757570/article/details/1122146067. 在封装better-scroll为全局组件时,会呈现监听的scroll事件无奈失效 查看了一下导致scroll事件无奈失效的一些起因: 1) DOM层级关系(wrapper外面不能存在多个同级div,若呈现多个同级div,则须要有一个div包裹住) 2) content是否被胜利增加滚动相干style 3) 只有content的高度大于wrapper高度时候,才能够滚动 4) .wrapper元素上要给定位 但调试来调试去,都如同不是这些起因 而后就试一下有没有可能是数据更新了,导致没有从新计算 better-scroll,后果在钩子函数updated中增加上了this.scroll.refresh(),就能够了 (当 DOM 构造发生变化的时候务必要调用确保滚动的成果失常) 8. 本来在有keep-alive缓存零碎的状况下更新数据,要把申请等操作都在activated生命周期中执行。但我在mounted中执行能够,在activated中就只执行了一次,好奇怪(有晓得导致这个问题的大佬能够在评论区评论哦!!!)9. 批改根底的公共根门路: 在vue-cli3.3之前的版本可利用baseUrl属性 在vue-cli3.3之后的版本可利用publicPath属性 (baseURL在vue-cli_3.3前面的版本中被弃用) 10. 在app.js文件中配置session时要留神放在路由申明前,否则不会失效
以上就是蜘蛛电影我的项目的大略内容了,有更多的性能可自行去欠缺
最初附上此我的项目大略的思维导图:
若有什么表白不当的中央,也欢送指出,一起提高哦!!!