Vue-cli3.0项目---蜘蛛电影(步骤解析)

项目简介

蜘蛛电影主要是仿猫眼电影的一个vue项目
主要功能:
1. 城市定位
2. 展示正在热映的电影
3. 展示即将上映的电影
4. 搜索
5. 展示影院
6. 我的页面
7. 电影详情

项目开发环境

编译工具:vscode
操作系统:win10
node环境:node 12.18.3  npm6.14.6
Vue脚手架: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 项目名
创建完后会生成一堆文件夹和文件:

image.png

在gitee创建项目对应的远程仓库
image.png

将本地库与远程库进行关联
image.png

把master分支中初始的项目文件/目录都推送到远程仓库中
image.png
image.png

创建并切换到dev分支,把dev分支的初始项目文件/目录也推送到远程仓库
image.png
image.png

创建并切换到一个新的分支(createComponents)用来专门创建组件
image.png

以下部分在createComponents分支上开发↓↓↓↓↓↓

初始化路由的配置---电影页面,影院页面,我的页面

总共有三个页面:电影页面,影院页面,我的页面
电影页面的路由配置:

image.png

影院页面的路由配置:

image.png

我的页面的路由配置:

image.png

在路由主配置页面(index.js)中引入各路由:

image.png

路由重定向的配置

当跳转的路由不存在,利用重定向默认跳转到电影页面(路径:/movie)
重定向:redirect:'跳转的路由'
在router文件夹下的index.js进行配置:

image.png

对项目中初始的index.html文件进行一些修改

//增加了user-scalable=no,不允许用户放大缩小页面
  
//引入公共的css样式
  
//引入图标
  

App.vue文件的修改

留出一个路由出口:
加上keep-alive标签:实现页面缓存作用,因为切换组件被重新渲染时会影响性能,会显著提高用户体验(会缓存不活动的组件)

image.png

创建头部组件

在components文件夹下创建一个header文件夹,并在此文件夹下创建index.vue文件
1. 编写相关的HTML,CSS代码
2. 为实现动态值(对应页面对应标题)的切换(实现父子组件的数据传递),可利用在Vue中的props(数据单向传递。父组件值的会改变子组件的值,子组件的值改变不会影响父组件)
   定义一个名称title,类型为String,默认值为'蜘蛛电影'
   然后在对应标签(

)中的内容处写上{{title}},接收传递过来的数据

image.png

创建尾部组件

在components文件夹下创建一个footer文件夹,并在此文件夹下创建index.vue文件
编写相应的HTML,CSS代码

image.png

创建页面组件---电影页面

在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标签,使其跳转到对应的子路由

image.png

配置电影页面中的子路由

电影页面中的子路由有:'city'(城市),'showing'(正在热映),'coming'(即将上映),'search'(搜索)
利用children来进行配置子路由(会拼接到/movie后面)
当在电影页面时,默认显示正在热映的页面,即路由重定向到'/movie/showing'

image.png

电影页面---创建城市的组件

在components文件夹下创建一个city文件夹,并在此文件夹下创建index.vue文件
1. 编写相应的HTML,CSS代码
   HTML中分为三部分:
   1) 热门城市
   2) 城市分类
   3) 首字母侧边栏

image.png

电影页面---创建正在热映的组件

在components文件夹下创建一个showing文件夹,并在此文件夹下创建index.vue文件
1. 编写相应的HTML,CSS代码
   HTML中分为每一部电影的区域
   而每一个电影区域中分为三部分:
   1) 电影图片
   2) 电影信息:电影名,电影分数,主演,影院场次
   3) 购票按钮

image.png

电影页面---创建即将上映的组件

在components文件夹下创建一个coming文件夹,并在此文件夹下创建index.vue文件
1. 编写相应的HTML,CSS代码
   HTML中分为每一部电影的区域
   而电影的每一个区域中分为三部分:
   1) 电影图片
   2) 电影信息:电影名,想观看人数,导演,主演,上映时间
   3) 预售按钮

image.png

电影页面---创建搜索的组件

在components文件夹下创建一个search文件夹,并在此文件夹下创建index.vue文件
1. 编写相应的HTML,CSS代码
   HTML中分为两部分:
   1) 搜索输入框
   2) 搜索结果展示区域:大类型,每一部电影对应的信息(电影图片,电影名,电影分数,电影英文名,电影类型,电影日期)

image.png

创建页面组件---影院页面

在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标签进行相应的渲染)

image.png

影院页面---创建展示影院的组件

在components文件夹下创建一个cinemalist文件夹,并在此文件夹下创建index.vue文件
1. 编写相应的HTML,CSS代码
   HTML中分为每一个影院的区域
   而每一个影院区域分为3部分:
   1) 影院名和价钱
   2) 地址和距离
   3) 一些折扣卡之类的

image.png

创建页面组件---我的页面

在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中就渲染一个登录页面的组件

image.png

我的页面---创建登录组件

在components文件夹下创建一个login文件夹,并在此文件夹下创建index.vue文件
1. 编写相应的HTML,CSS代码
   HTML中分为五个部分
   1) 账户名输入框
   2) 密码
   3) 验证码
   4) 登录按钮
   5) 找回密码和立即注册

image.png

到目前为止,在createComponents分支上的开发大概已完成了,可以把此分支上的东西合并到dev分支上,再推送到远程仓库中

1. 在createComponents分支:git add .,git commit提交代码到本地库
2. 切换到dev分支:git checkout dev
3. 合并到dev分支上:git merge createComponents --no-ff
4. 推送代码到gitee的远程库中:git push origin dev
5. 可以删除createComponents分支:git branch -d createComponents

接下来可继续进行相应的开发了

创建新分支setData,专门用来渲染数据的

创建并切换分支setData:git checkout -b setData

以下操作均在setData分支上开发↓↓↓↓↓↓

我把相关数据的api文件都放在Tomcat搭建的服务器上,由于数据存放的ip地址为localhost:8082,而项目运行的ip地址为localhost:8081
所以在渲染数据的时候就存在一个跨域问题

解决跨域问题

在项目目录中新建文件:vue.config.js
编写:(编写完后记得重启项目,才会生效)

image.png
image.png

渲染数据时使用axios来进行一个ajax的请求

1. 安装axios:npm i -S axios
2. 引入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       

城市组件---渲染城市数据

部分城市数据:

image.png

1. 在data(){return {}}中定义两个数据:hotlist数组(接收传递过来的热门城市数据),citylist数组(接收传递过来的普通城市数据)

image.png

2. 在city组件中,在生命周期为mounted的钩子函数中,利用axios的get请求取得城市数据

image.png

3. 随后将数据渲染到页面上(利用v-for)

image.png

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')

image.png
image.png

正在热映组件---渲染正在热映的电影数据

部分正在热映的电影数据:

image.png

1. 在data(){return {}}中定义一个数据:movielist数组(接收传递过来的正在热映的电影数据)

image.png

2. 在showing组件中,在生命周期为mounted的钩子函数中,利用axios的get请求取得正在热映的电影数据

image.png

3. 随后将数据渲染到页面上(利用v-for)
   其中传递过来的图片路径需要经过一些宽高设置的处理(使用Vue3.x的过滤方法(在main.js文件编写))
   还有显示怎样版本的图片标识可用v-if来进行判断

image.png
image.png

即将上映组件---渲染即将上映的电影数据

部分即将上映的电影数据:

image.png

1. 在data(){return {}}中定义一个数据:cominglist数组(接收传递过来的即将上映的电影数据)

image.png

2. 在coming组件中,在生命周期为mounted的钩子函数中,利用axios的get请求取得即将上映的电影数据

image.png

3. 随后将数据渲染到页面上(利用v-for)
   其中传递过来的图片路径需要经过一些宽高设置的处理(使用Vue3.x的过滤方法(在main.js文件编写))
   还有显示怎样版本的图片标识可用v-if来进行判断

image.png
image.png

搜索组件---渲染搜索结果的数据

部分搜索结果的电影数据:(这里只提供了有关字母a,b,aaa的数据)

image.png

1. 在data(){return {}}中定义一个数据:message字符串(输入框的值),movielist数组(接收传递过来的电影数据)

image.png

2. 在search组件中,在watch的钩子函数中,若message发生变化,则利用axios的get请求取得搜索得到的电影数据(在watch中,可做函数节流,Ajax异步数据获取,操作DOM;依赖固定的数据类型等。一个原本就存在的数据,发生变化就执行函数)
   1) 在input标签中,利用v-model双向绑定message数据,监听输入框的值
   2) 在监听message中进行axios的get请求

image.png
image.png

3. 随后将数据渲染到页面上(利用v-for)
   其中传递过来的图片路径需要经过一些宽高设置的处理(使用Vue3.x的过滤方法(在main.js文件编写))

image.png
image.png

4. 在输入框输入数据的这种实时监测数据的情况下,只要最后一次确定的结果,前面的都清除掉。(即在这期间axios会触发多次请求,要把没用到的请求中断掉)
这个时候就要使用函数防抖的一个手段:
1. 可使用定时器的方式
2. 也可利用axios终止请求的一些方法
   1) 一开始可先判断终止请求的函数是否已经存在了,若存在就终止
   2) 在axios的第二个参数中新建一个cancelToken的实例(利用axios的构造函数CancelToken)(使得请求具有可以取消的功能)

image.png

cinemalist组件---渲染影院的数据

部分影院的数据:(这里只提供了江门,成都的影院数据)

image.png

1. 在data(){return {}}中定义一个数据:cinemalist数组(接收传递过来的影院数据)

image.png

2. 在cinemalist组件中,在生命周期为mounted的钩子函数中,利用axios的get请求取得影院的数据

image.png

3. 随后将数据渲染到页面上(利用v-for)
   还有显示怎样小卡片可用v-if来进行判断

image.png

4. 在后面的步骤,会实现根据不同的城市地区渲染不同地区的影院数据

到目前为止,在setData分支上的开发大概已完成了,可以把此分支上的东西合并到dev分支上,再推送到远程仓库中

1. 在setData分支:git add .,git commit提交代码到本地库
2. 切换到dev分支:git checkout dev
3. 合并到dev分支上:git merge setData --no-ff
4. 推送代码到gitee的远程库中:git push origin dev
5. 可以删除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-scroll
2. 在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文件中编写:

image.png

better-scroll组件全局的编写:

image.png

better-scroll组件的调用:

image.png

全局封装loading组件

由于有些内容都要通过请求加载出来,在等待数据响应的过程中,可以在加载的过程中添加一个loading组件,看上去也会更美观一点,用户的体验感也会更好

1. 在components文件夹下创建一个loading文件夹,并在此文件夹下创建index.vue文件
2. 编写HTML,CSS部分
   (可自己写,也可直接去找一些css3实现loading效果的组件,推荐网址:https://codepen.io/trending)
3. 全局注册此组件,使得可以在文件中随时使用。在main.js文件中编写:

image.png

loading组件全局的编写:

image.png

loading组件的调用:
(可在data中定义一个Boolean类型的数据:isLoading,为true就显示loading组件,否则就显示better-scroll组件)

image.png

设置城市数据的本地存储与状态管理

对于一些不怎样变化的数据,可以存储到本地(如:localStorage)

城市数据的本地存储:(利用localStorage)
1. 当通过ajax请求得到的数据后,利用window.localStorage.stetItem('xx',xx)来存储数据(注意要先用JSON.stringfy方法来变为字符串再存放)
2. 在ajax请求前,可以先做一个判断,若本地存储中有相关数据,则直接进行赋值(注意取出数据时先要用JSON.parse方法来变为JSON对象再赋值),否则就进行ajax请求取得数据

image.png

城市数据的状态管理:(这里就要用到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
       }

image.png
image.png

5. 在电影组件(movie)的城市标签显示中,获取到store状态里的city模块的城市名来实现动态显示城市数据(获取对应的属性值:$store.state.模块名.模块属性)

image.png

6. 在city组件中,实现点击每一个城市就会更新当前的城市状态信息并存储起来
   1) 为每个城市li绑定click事件,并执行handleToCity()方法
   2) 在handleToCity方法中:
      通过this.$store.commit("模块名/模块中的mutations", {对应的值})方法把接收到对应的城市名和城市id都传给city的状态管理并更新
      利用localStorage存储当前状态的城市名和城市id
      选择完城市后,利用this.$router.push('路由路径')来自动跳转到正在上映的电影页面

image.png
image.png

通过当前城市的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

image.png

全局封装弹窗组件

若利用vue来创建这个组件,在传参数或者复用的时候会有点麻烦,所以我们这里可以利用JS来封装此组件,并接收对应的参数
1. 在components文件夹下创建一个名为JS的文件夹,在JS文件夹下创建一个index.js文件(作为JS主模块文件),在JS文件下创建一个名为msgBox的文件夹,在msgBox文件夹下创建一个index.vue

2. 在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,并挂载

image.png

4. 然后继续编写msgBox对应的index.vue文件
   要接收传过来的插槽属性值,可利用v-slot和slot的配合
   要接收props的值,先在props:{}中定义那两个函数值,通过this.$props.xxx来调用对应的函数方法

image.png

这里是关于弹窗的一下小改进:
1. 在cancel和ok对应的区域中,判断哪个有值就显示哪个区域(利用v-if)
2. 点击ok区域后也要移除掉弹窗并解除绑定
3. cancel和ok值都当做props属性传进去,并在对应的msgBox vue组件中进行接收

image.png
image.png

实现城市定位

城市的定位是在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中,数据更新了就重新判断一下当前的城市状态和当前定位的城市是否相等,看是否需要重新定位  

image.png

到目前为止,在getCity分支上的开发大概已完成了,可以把此分支上的东西合并到dev分支上,再推送到远程仓库中

1. 在getCity分支:git add .,git commit提交代码到本地库
2. 切换到dev分支:git checkout dev
3. 合并到dev分支上:git merge getCity --no-ff
4. 推送代码到gitee的远程库中:git push origin dev
5. 可以删除getCity分支:git branch -d getCity

接下来可继续进行相应的开发了

创建新分支detailPage,专门开发电影详情页面

创建并切换分支detailPage:git checkout -b detailPage

以下操作均在detailPage分支上开发↓↓↓↓↓↓

创建组件---电影详情页面组件

1. 电影详情页面的渲染入口:
电影详情页面的组件渲染,可以通过在movie组件中通过router-view命令视图来渲染出来
但这样一来,就会和之前写的渲染正在上映和即将上映的组件的router-view产生冲突了,这个时候我们可以通过name来把它们区分开来(即命名视图),导致不让它们渲染混乱
我们把渲染电影详情组件的命令视图的name设为detail

image.png

2. 接下来就要在movie的路由中设置详情页的路由
由于使用了命名视图,所以在对应子路由渲染组件的时候,写法也会稍微不一样
而且可通过路由传参的方式把在电影页面得到的电影id值传给电影详情页面,电影详情页通过props接收传过来的id值,可请求到对应的电影详情数据并渲染出来
以下图片是相关的路由配置

image.png

3. 编写电影详情页的组件
  1) 在views文件夹下的movie文件夹中,新建一个名为detail.vue的文件
  2) 编写相关的HTML,CSS
     引入header组件,因为要在头部的左侧加上一个回退上一级功能,所以需要增加一个图标,在header组件中新增加一个插槽用来渲染图标

image.png

  3) 定义props属性来接收从电影页面传过来的电影id(路由中定义的属性名是什么,这里的props属性名就定义什么)
  4) 定义一个handleToBack方法实现返回上一级路由,利用 this.$router.back()方法来实现
  5) 然后就是利用ajax请求接收数据了,通过和接收到的电影id配合,来取得相应的电影详情数据
  6) 其中在演职人员的展示中,我们可以利用swiper插件来实现移动端的滑动展示(要引入swiper相关的CSS,JS文件)
     (swiper中文网:https://www.swiper.com.cn/)

image.png

到目前为止,在detailPage分支上的开发大概已完成了,可以把此分支上的东西合并到dev分支上,再推送到远程仓库中

1. 在detailPage分支:git add .,git commit提交代码到本地库
2. 切换到dev分支:git checkout dev
3. 合并到dev分支上:git merge detailPage --no-ff
4. 推送代码到gitee的远程库中:git push origin dev
5. 可以删除detailPage分支:git branch -d detailPage

以上基本就是客户端的一些开发了,你也可以自行完善一些其他的功能

也可以进行一下真机测试,即在手机上浏览开发的这个项目

进行真机测试的前提,就是手机和电脑要连接到同一个网络
查看运行项目时的Network的地址,直接在手机浏览器中输入这个地址就可以查看了

image.png

若你这里显示的Network地址为unavailable
解决方法:
在vue.config.js文件中,添加一个public属性,属性值为此网络的IPv4地址,并加上相应的端口号,重启项目,就有显示啦

image.png

项目的一些优化

1. 可以在此项目开始的时候,加一个等待加载的动画(在index.html文件中添加)
2. 修改基础的公共根路径(可以指定一个根目录,在此目录下访问所有的文件,组件)
   利用publicPath来修改生产模式和开发模式的基础公共根路径(在vue.config.js文件下配置)
   这是我的配置修改:

image.png

项目的打包

项目打包命令:npm run build
打包后的文件放在dist目录中

image.png

下面是后端的操作↓↓↓↓↓↓

我们的后端开发需要用到的技术

1. Node.js
2. Express
3. MongoDB
4. 其他模块

后端开发的前提准备

为实现关于我的页面的对应功能,需要进行后台管理的开发,利用数据库存储用户的对应信息
安装node (可查看我的另一篇文章:关于node)
安装express:npm i -s express
可全局安装express-generator:npm install -g express-generator
(express-generator会快速创建应用程序框架)

在项目目录spider的同级目录下,打开cmd
输入命令:express -e 服务框架名

image.png

然后就会生成对应的一个目录

image.png

进入此目录,打开package.config文件,如果你想实时修改(监听)文件
可把scripts中的"start": "node ./bin/www"改为"start": "nodemon ./bin/www"(前提是要安装nodemon的这个插件)
运行后,在浏览器输入对应的地址(我这里设置的端口是3000),若出现下图的内容,则证明已经打开成功

image.png

由于我们要用到数据库来存储我们的用户数据,我们这里就使用MongoDB数据库
我们可以安装mongoose模块,利用express来对其操作数据
安装mongoose:npm i -S mongoose
然后在spiderserver目录下新建一个名为db的文件夹,用来存放数据库的数据
打开数据库:(若你已经配置了mongodb的全局路径,可在任意一处输入命令。若没有,则要在对应的mongodb的bin目录下打开cmd输入命令)
输入命令:mongod --dbpath=db文件夹的路径
我们可以新建一个名为untils的文件夹,在此文件夹下新建一个名为config.js的文件,这个文件是专门用来编写数据库和一些模块的相关配置
编写config.js文件:

image.png

然后再app.js文件中引入刚编写的mongoose模块文件:var {Mongoose}=require('./untils/config');
并调用它的连接数据库方法:Mongoose.connect();
随后可通过命令行或者可视化的数据库工具Robo 3T来创建我们对应的数据库(具体操作可查看我的另一篇文章《关于MongoDB》)
我这里就使用可视化的数据库工具来创建

image.png

创建完成后,我们就可以再次启动我们的服务器,看数据库是否连接成功,若出现如下图的情况,则表示已连接成功

image.png

关于我的页面需要编写的相关接口

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模块):

image.png

在controllers文件夹下的users.js文件中先引入untils下的users.js模块的Email对象,再编写verify接口的处理方法:

image.png

在routers文件夹下的index.js文件中先引入controllers文件模块,调用其verify接口的处理方法,然后配置verify接口的路由:(get请求)

image.png

设置验证码的时效性:
1. 在spiderserver/config/untils下的Email对象中新增一个获取当前时间的方法

image.png

2. 在spiderserver/controllers/users.js下的验证接口处理方法中,把发送验证码的时间存入session中

image.png

3. 在spiderserver/controllers/users.js下的注册接口处理方法中,用当前的时间减掉刚才存入session中的发送验证码的时间,判断有没有超过60秒,若超过60s则证明验证码已过期

image.png

编写我的页面的接口---注册接口register

为了能在注册的时候拿到验证时的验证码,需要对数据进行持久化操作,存入session中(利用express的中间件express-session)
安装express-session:npm i -S express-session
在app.js文件中引入express-session模块:var session=require('express-session');
引入模块后可进行相关的配置:(记住要在路由声明前进行配置)

image.png

在验证接口中把接收邮箱和验证码都存入session中:
req.session.verify=verify; 
req.session.email=email; 

因为用户的注册信息需要保存到数据库中,所以在models/users.js下进行相关的编写:
1. 定义注册接口的数据库骨架
2. 定义对应的数据库模型(注意让唯一值生效的做法)
3. 定义一个数据保存的方法

image.png

随后在controllers/users.js下编写注册接口的处理方法:
1. 引入刚定义的数据库模型
2. 获取到用户进行post请求的注册数据
3. 判断传进来的邮箱或者验证码是否与session中存放的相等
4. 利用定义的数据保存方法保存相应的用户名,密码,邮箱
5. 然后根据保存的结果判断是否注册成功

image.png

在routers文件夹下的index.js文件中配置rigister接口的路由:(post请求)
router.post('/register',usersController.register);

编写我的页面的接口---登录接口login

在models/users.js下编写数据库查找数据的方法:

image.png

在controllers/users.js下编写注册接口的处理方法:
1. 获取到用户进行post请求的登录数据
2. 根据用户传过来的登录数据在数据库进行查找匹配
3. 然后根据查找的结果判断是否登录成功,若登录成功则把username存入session中

image.png

在routers文件夹下的index.js文件中配置login接口的路由:(post请求)
router.post('/login',usersController.login);

编写我的页面的接口---登出的接口logout

在controllers/users.js下编写登出的处理方法:直接把存储在session的用户名变为空

image.png

在routers文件夹下的index.js文件中配置logout接口的路由:(get请求)
router.get('/logout',usersController.logout);

编写我的页面的接口---获取用户信息的接口getUser

在controllers/users.js下编写获取用户信息的处理方法:
判断session中的username是否为空,不为空则获取成功并把相应的用户数据存放到session中,否则获取失败

image.png

在routers文件夹下的index.js文件中配置getUser接口的路由:(get请求)
router.get('/getUser',usersController.getUser);

编写我的页面的接口---找回密码的接口findPassword

在models/users.js下编写更新数据库数据的方法:(根据传过来的对应邮箱进行更新)

image.png

在controllers/users.js下编写找回密码的处理方法:
1. 获取到用户进行post请求的相关数据
2. 判断传过来的邮箱和验证码是否和session存储的一样
3. 若一样,则调用usreModel下的updatePassword方法对密码进行修改,否则失败

image.png

截止目前,有关我的页面的用户接口已经写完了
接下来继续开发我的页面的组件↓↓↓↓↓↓

配置我的页面的子路由

在src/router/mine/index.js中配置我的页面相关的子路由(包括登录组件,个人中心组件,注册组件,找回密码组件)
当显示我的页面时,重定向路由到个人中心页面

image.png

完善之前创建的登录组件的功能

1. 在data中定义两个数据:username(用户名),password(密码)
2. 对用户名的输入框和密码的输入框都利用v-model分别对username,password数据进行双向绑定
3. 给登录按钮添加一个touchstart事件,执行handleToLogin方法
4. 编写handleToLogin方法:
   1) 向之前编写的登录login接口进行ajax请求(记得先进行对应的反向代理,要不然会出现跨域无法访问的问题,反向代理时本地编写的接口最好放在前面,以免有些不必要的错误)
   2) 根据status来判断是否登录成功(登录成功则跳转到个人中心的页面)
   3) 引入弹窗组件,利用弹窗组件对其进行一个反馈信息的作用

image.png
image.png

设置用户的一些状态管理

在store文件夹下新建一个名为user的文件夹,在此文件夹下新建一个index.js文件并编写。随后在store/index.js中引入该文件模块

image.png
image.png

创建我的页面的相关组件---个人中心组件

1. 在views/mine下新建一个名为center.vue的文件
2. 编写相应的HTML,CSS
   HTML部分中,当前用户名通过$stor.state.xxx.xxx显示出来

image.png

3. 对退出按钮添加一个touchstart事件,并编写handleToLogout方法:
4. 通过对logout接口进行ajax请求,通过status判断是否登出成功,登出成功则跳转到登录页面并更新用户状态管理的用户名为空

image.png

5. 在进入个人中心页面前可以先利用"导航守卫"判断一下当前用户的登录状态再决定是否可以进入此组件(用户的登录状态可利用向getUser接口发起请求来判断)
   若此时用户为登录状态则可以进入个人中心页面并更新用户状态管理的用户名为当前用户的用户名,反之则跳转到登录页面

image.png

创建我的页面的相关组件---注册组件

1. 在components新建一个名为register的文件夹,在此文件夹下新建一个index.vue文件
2. 编写相应的HTML,CSS

image.png

3. 在data中定义六个数据:username(用户名),password(密码),email(邮箱),verify(验证码),verifyInfo(验证码的相关信息),disabled(判断按钮是否禁用状态)
4. 对用户名的输入框,密码的输入框,邮箱的输入框和验证码的输入框都利用v-model分别对username,password,email,verify数据进行双向绑定
5. 引入弹窗组件,利用弹窗组件对其进行一个反馈信息的作用
6. 对发送验证码的按钮添加一个touchstart事件,并编写handleToVerify方法:(利用ajax对verify接口进行请求)
   点击确定后触发countDown方法

image.png
image.png

7. 对注册的按钮添加一个touchstart事件,并编写handleToRegister方法:(利用ajax对register接口进行请求)

image.png

创建我的页面的相关组件---修改密码组件

1. 在components新建一个名为findPassword的文件夹,在此文件夹下新建一个index.vue文件
2. 编写相应的HTML,CSS

image.png

3. 在data中定义三个数据:password(密码),email(邮箱),verify(验证码)
4. 对密码的输入框,邮箱的输入框和验证码的输入框都利用v-model分别对password,email,verify数据进行双向绑定
5. 引入弹窗组件,利用弹窗组件对其进行一个反馈信息的作用
6. 对发送验证码的按钮添加一个touchstart事件,并编写handleToVerify方法:(利用ajax对verify接口进行请求)

image.png

7. 对确认修改的按钮添加一个touchstart事件,并编写handleToPassword方法:(利用ajax对findPassword接口进行请求)

image.png

接下来是开发后台管理页面↓↓↓↓↓↓

设置后台管理的管理员接口与权限

1. 先在spiderserver/models/users.js中的数据库骨架新增一个值为isAdmin,此值为Boolean类型。用于判断是否有管理权限

image.png

2. 在spiderserver/contorllers/user.js中,在登录接口的处理方法中,当登陆成功时,也把其管理权限的值也存入到session中,以便以后判断是否有管理权限。在获取用户信息接口的处理方法中,当获取成功时,把其管理权限的值存入到data中

image.png
image.png

3. 在spiderserver/routes下新建一个名为admin.js的文件,配置管理页面的接口路由
   1) 先设置一个拦截器,用于判断其用户的管理权限,才可进入管理页面
   2) 配置管理页面的主页路由

image.png

4. 在spiderserver/app.js中引入该管理页面的路由

image.png
image.png

后台管理页面是利用element-ui组件库搭建的

element-ui中文官网:https://element-plus.gitee.io/#/zh-CN
1. 安装element-ui插件:npm i -S element-ui
2. 在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文件
其子路由包括用户管理页面路由,电影管理页面路由,影院管理页面路由

image.png

随后在spider/src/router下的index.js文件下引入该路由文件模块

image.png

创建管理后台组件---主页面组件

1. 在spider/src/views下新建一个名为admin的文件夹,在此文件夹下新建一个index.vue文件
2. 编写相应的HTML,CSS(布局为头部,侧边栏,主区域)

image.png

3. 在spider/store/user/index.js下,新增用户的一个管理员状态值isAdmin,默认值为false

image.png

4. 在个人中心页面根据其是否为管理员渲染用户的身份,若为管理员则添加一个router-link标签来跳转到后台管理页面
   1) 在获取到用户信息后,把用户的管理权限的值更新到用户的状态管理中
   2) 登出的时候,用户状态管理中的管理权限的值为false

image.png
image.png

5. 在管理后台的主页面中,利用导航守卫来判断当前用户是否有管理权限来进入管理后台

image.png

创建管理后台组件---用户管理组件

1. 在spider/src/views/admin下新建一个user.vue文件

2. 编写相应的HTML,CSS(表格区域分为账号创建日期,用户名,邮箱,操作(未冻结和删除))

image.png

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项删除掉)

image.png

7. 对于冻结的账号,登录时应提示账号已冻结,登录失败
   在spiderserver/controllers/users.js下编写一些相应判断

image.png

   在login组件中也要在弹窗中反馈对应的信息

image.png

8. element-ui对数据进行分页处理
   1) 引入分页组件

image.png

   2) 在data中定义两个数据:currentPage(当前页),pageSize(每页显示的数据)
   3) 通过computed根据当前页和每页显示的数据来计算nowTableData的每一页渲染的数据,此时table应该是渲染nowTableData的数据

image.png

   4) 编写handleCurrentChange方法来改变当前页的值

image.png

创建管理后台的接口---用户管理接口

在用户管理接口中,要实现三个方法:
1. 显示所有用户数据的方法
   1) 在spiderserver/models/users.js下编写一个返回显示所有用户数据的方法

image.png

   2) 在spiderserver/controllers/admin.js下编写显示所有用户信息的操作的处理方法(引入models中刚编写的方法)

image.png

   3) 在spiderserver/routes/admin.js下配置显示用户数据的接口路由:router.get('/userList', adminController.userList);

2. 账号冻结操作的方法
   1) 在spiderserver/models/users.js的数据库骨架中,新增一个值为isFreeze,此值为Boolean类型。用于判断用户账号是否被冻结

image.png

      在spiderserver/models/users.js下编写一个数据库更新账号的冻结状态的方法(以邮箱号为标识来更新isFreeze的值)

image.png

   2) 在spiderserver/controllers/admin.js下编写更新账号的冻结状态操作的处理方法(引入models中刚编写的方法)

image.png

   3) 在spiderserver/routes/admin.js下配置账号冻结的接口路由:router.post('/updateFreeze', adminController.updateFreeze);

3. 账号删除的方法
   1) 在spiderserver/models/users.js下编写一个数据库删除用户账号的方法(以邮箱号为标识来删除)

image.png

   2) 在spiderserver/controllers/admin.js下编写删除用户账号操作的处理方法(引入models中刚编写的方法)

image.png

   3) 在spiderserver/routes/admin.js下配置账号删除的接口路由:router.post('/deleteUser', adminController.deleteUser);

关于用户头像上传的操作

编写用户头像上传的接口:
1. 在spiderserver/models/users.js下的数据库骨架中添加一个值为userHead,类型为String,默认值为http://localhost:3000/images/default.jpg,表示用户的头像

image.png

2. 在spiderserver/models/users.js下编写数据库更新用户头像的方法

image.png

3. 在spiderserver/untils/config.js下编写用户头像上传的基础公共路径

image.png

4. 在spiderserver/controllers/users.js下编写更新用户头像的方法(先引入刚编写的config.js的Head对象,fs模块)

image.png

5. 后端上传东西可以利用node中的multer模块(详情用法可参考文档:http://expressjs.com/en/resources/middleware/multer.html)
   1) 在spiderserver/routes/users.js下引入multer模块,并指定头像的上传路径

image.png

   2) 配置上传文件接口的路由

image.png

前端的操作:
1. 在用户的管理状态中新增一个状态量userHead,初始值为空串

image.png

2. 在进入个人中心页面前,若进入成功,也要更新一下用户头像状态的值

image.png

3. 登出页面的时候,把用户头像状态的状态值变为空串

image.png

4. 在个人中心页面组件中添加一个区域,是负责上文头像文件的

image.png

5. 在上传文件的按钮上绑定一个touchstart事件,执行编写的handleToUpload方法
   需要注意的是在调用用户头像上传的这个接口时,要传入文件的相关参数(利用FormData()对象,更多FormData的用法可参考:https://www.cnblogs.com/wssdx/p/11244766.html)和传入"Content-Type"的值是为"multipart/form-data"
   更新用户头像的状态值时记得在后面加个随机数来清除缓存

image.png

6. 在后台管理页面中,新增一列来存放用户上传的头像

image.png

项目优化---密码加密

加密可使用node中的crypto模块
1. 在spiderserver/untils下新建一个base.js,用来编写加密的相关方法
   1) 引入crypto模块:const crypto = require('crypto');
   2) 编写一个加密方法setCrypto

image.png

2. 在spiderserver/controllers/users.js,先引入上面编写的文件模块,再去设置存放密码为加密的密码形式
   如:

image.png

项目优化---登录时防攻击验证码

利用node的trek-captcha模块生成图形验证码
1. 在spiderserver/untils/base.js下引入trek-captcha模块,再编写图形验证码生成方法

image.png

2. 在spiderserver/controllers/users.js,先引入上面编写的文件模块,再去编写生成图形验证码的处理方法

image.png

3. 在spiderserver/routes/users.js下配置生成图形验证码的接口路由:

image.png


在login组件中使用此组件:
1. HTML中新增加一个区域:填写验证码

image.png

2. 为img标签绑定一个touchstart事件,执行编写的handleToVerifyImg方法实现点击图片更新验证码

image.png

3. 当登陆失败点击确定后,也要重新刷新图片验证码(在img标签添加一个ref属性,属性值为verImg,用于获取到该img元素)

image.png

关于项目的线上部署

把打包好的项目交给后端,后端要选取一个web服务器(http服务器)
我们这次选取的一个web服务器是nginx
什么是nginx?
为什么要选择nginx呢?
nginx的好处有哪些呢?
以上的种种问题可移步至另一篇文章《关于nginx》!!!

而上线项目,则需要有一个云服务器(对应的域名或一个IP地址),可以去阿里云,腾讯云等看看

云服务器都设置好以后,可通过windows的远程连接来连接远程服务器,在远程服务器中也安装nginx,配置对应的反向代理

截止目前,就可以在浏览器上访问公有的IP地址,就可以访问到我们的这个项目了

项目过程中遇到的一些问题

1. 在gitee创建远程仓库时没有把readme初始化仓库那一项去掉,导致一开始的远程库不是一个空仓库,所以无法把本地库中的初始项目推送到远程库中,一直卡住
   git push时出现的报错:(大概如下)

image.png

   解决方法也可参考网址:https://blog.csdn.net/cuomer/article/details/81142159

2. 在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/112214606

7. 在封装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时要注意放在路由声明前,否则不会生效

以上就是蜘蛛电影项目的大概内容了,有更多的功能可自行去完善
最后附上此项目大概的思维导图:
image.png

若有什么表达不当的地方,也欢迎指出,一起进步哦!!!

你可能感兴趣的:(Vue-cli3.0项目---蜘蛛电影(步骤解析))