项目代码css
一.项目环境准备html
Vue项目运行在NodeJ环境中,npm为NodeJs的包管理工具,命令行 node -v ,npm -v 中查看系统是否已经安装Node环境。若是还没安装环境,就前往 Node官网下载吧。
接着安装 vue-cli 脚手架工具,vue-cli可以帮助咱们快速构建Vue项目。安装脚手架:npm install --global vue-cli,建立vue项目: vue init webpack my-project,npm install 运行项目: npm run dev。前端
二.项目代码结构介绍vue
下面来介绍下vue项目目录html5
README.md 项目说明文件node
package.json 项目开发须要的第三方依赖包webpack
LICENSE 开源协议的说明ios
index.html 项目默认首页文件git
.prostcssrc.js github
.gitignore
.eslintrc.js 配置代码规范
.eslintignore 文件不受代码规范限制
.editorconfig 编辑器语法
.bablelrc 经过bable语法解析,编译可以执行的代码
static 静态资源 存放静态图片 mock模拟数据
src 整个项目的源代码
main.js项目入口文件
App.vue项目原始根组件
router/index.js 整个项目的路由配置
components项目须要的组件
assets 项目须要的图片
node_modules 项目依赖的第三方node包
config 项目配置文件
index.js基础配置信息
dev.env.js 开发环境配置信息
prod.env.js 线上生产环境配置信息
build 项目打包webpack配置内容
三. 单文件组件与Vue中的路由
单文件组件.vue 是由组件模板<template></template>,组件逻辑结构<script></script>,组件样式<style></style> 三部分构成。
路由就是根据网址的不一样,返回不一样的内容给用户。路由配置通常都在router目录下的index.js下啦。说到路由,不妨提下Vue中的页面路由:原生中能够经过<a>标签和 js的href属性进行页面的跳转,Vue 一样也有两种方法进行路由,分别是:<router-link to=' ' > 和 this.$router.push('/') 。
路由后拖动,多个界面之间会互相影响。在路由配置页index.js添加如下代码便可:
scrollBehavior (to, from, savedPosition) {
return { x: 0, y: 0 }
}复制代码
Vue是单页面应用,那单页面应用和多页面运用又有什么区别呢?
页面跳转 ——> JS渲染
优势:页面切换快 (js会感知url的变化,经过js感知到url的变化,js 动态地把当前页面的内容清楚掉,再把下一个页面的内容挂载到页面上。这时候,路由不是后端来作,而是前端来作。)
缺点:首屏时间稍慢 (首屏展现出来须要请求一次html和发送一个JS的请求,两个请求都回来了,首屏才会被展现出来),SEO差。
vue中还提供了服务器端等技术,经过这些技术,能够完美地解决单页面应用的这些问题。
多页面应用(MultiPage Application,MPA)
指的是页面跳转—— >返回HTML
优势:首屏时间快,SEO效果好(搜素引擎优化效果好,搜索引擎在作网页排名的时候须要知道网页的内容,根据网页内容给予权重从而进行排名。搜索引擎能够识别html中的内容的)。
缺点:页面切换慢 (每次跳转页面的时候都须要发送http请求,网络比较慢的时候,在页面来回跳转的时候,会出现明显的卡顿状况)。
五.项目代码初始化
在正式编写代码以前,咱们先进行一些代码的初始化。
a.在默认首页文件index.html 完善<meta>标签的viewport配置
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
复制代码
这样的话,要求用户对于移动设备的放大缩小都是无效的,而且页面的比例始终是1:1。
b. 在项目入口文件main.js中引入重置页面样式表reset.css
import './assets/styles/reset.css'
复制代码
c.引入一像素边框文件
(1像素边框问题)有的手机屏幕分辨率比较高,为2倍屏或者3倍屏。若是在页面上写 border:1px solid black;这时候写的是1px,指的是css像素。可是在2倍屏上1px css像素对应的不是1个物理高度的像素,而是两个物理高度的像素。
d. 安装第三方依赖库fastclick
(移动端有300毫秒点击延迟的问题) 移动端开发中,在某些机型上,某些浏览器上,当使用click 点击事件的时候,click 事件会延迟300 毫秒后才执行。
安装fastclick 库 (--save表示不管在开发环境或者生产环境中都使用 fastclick)
npm install fastclick --save复制代码
引入
import fastClick from 'fastclick'
复制代码
使用
fastClick.attach(document.body)
复制代码
e. iconfont管理
去iconfont官网注册登陆建立本身的项目,选择你要的图标加到购物车,都选择完后,将购物车的图标都加到项目中,而后下载到本地,选择字体文件和iconfont.css添加到Vue项目中,并在main.js文件中import。而后就可使用啦,类名为“iconfont" ,为图标对应的进制代码,官网里能够查看。(不要忘记修改iconfont.css里的字体文件的路径)
<span class="iconfont"></span>
复制代码
e.项目中使用stylus
安装依赖包 npm install stylus --save
npm install stylus-loader --save
<style lang="stylus" scoped>
使用stylus ,scoped 局部化样式 表示样式只对当前组件起做用,不影响其余组件。
项目中咱们使用rem作自适应布局,rem是根据html的font-size大小来变化,html font-size = 50px =1rem (为方便计算,html font-size能够根据本身设置)
f.代码优化,定义样式变量
新建一个varible.styl 文件,定义样式变量
$bgColor = #00bcd4
复制代码
在组件样式中引入文件(<style>样式中引入import前要加@)
@import '../../../../assets/styles/varibles.styl'复制代码
此时文件路径很长,容易搞错,@表明src目录 ,因此咱们能够将路径修改为:(记得在@前加~)
@import '~@/assets/styles/varibles.styl'
复制代码
在stylus中使用
background: $bgColor复制代码
另外,有的目录咱们常用到,好比stylus目录,那有什么办法给目录起个别名呢?让咱们更方便地访问。(就好像src目录的别名是@ 同样)
解决办法:打开build目录下的 webpack.base.conf.js 文件,找到 alias 别名项
'@': resolve('src'),
复制代码
根据src 的配置,能够配置你想要的路径的别名,如
'styles': resolve('src/assets/styles'),
复制代码
那么咱们就能够更改上面复杂的路径了
@import '~styles/varibles.styl'
复制代码
(提示:当我更改了webpack配置项的时候,记得重启服务器,ctr c npm run start)
六.码云的运用
个人项目放在码云上面啦,固然更推荐你们使用github~
首先在码云上建立项目,具体的这里就很少说啦。而后 git clone adress 下载码云仓库代码到本地(SSH代码协议进行克隆)。
建立git分支。在真正的企业级别的开发中,咱们每开发一个新的功能,都要建立一个git的分支,在分支上进行代码的开发。当代码开发完成以后,把分支的代码合并到master主分支上。
而后在git bansh终端运行 git pull ,就会将咱们建立的 index-swiper 分支 拉到本地来。
在运行 git checkout index-swiper ,这时候本地所在的分支就切换到 index-swiper 分支了。
将代码保存到本地仓库,并提交到线上仓库。
git add . git commit -m ' ' git push
这个时候本地的index-swiper分支就提交到线上index-swiper分支了。
而后再将index-swiper分支上的内容合并到master分支上。
git checkout master //先切换到master分支上
git merge origin/index-swiper //而后把线上的index-swiper分支上新增的内容合并到本地
的 master分支上。
git push //将本地的master分支提交到线上。
master分支放的上整个项目全部功能的最新代码。index-swiper放的是开发的具体功能的开发完成时的代码。因此在实际企业级新项目开发中,咱们会本身开发一个分支,测试没有问题后,再把这个分支的代码合并到主分支上。
七.AJAX获取数据
axios第三方模块,能够实现跨平台的数据请求。axios十分强大,在服务器端axios能够帮助你发送xhr的请求;在node服务器上,能够帮助你发送http请求。
安装axios
npm install axios --save复制代码
引入
import axios from 'axios'
复制代码
使用mock模拟数据
axios.get('/static/mock/index.json')
咱们如今用的都是本地模拟接口的地址,加入代码要上线,在上线以前,须要把这块地址从新替换成 axios.get('/api/index.json') 这种格式,上线以前去改代码,是有风险的。不建议你们这么作。那怎么才能解决这个问题呢?咱们想,在开发环境中,咱们依然这么写咱们的路径 axios.get('/api/index.json'),若是有一个转发机制,可任意帮助咱们把 对api下全部json文件的请求 转发到本地的mock文件夹下。vue提供了proxy的代理功能,就能够实现咱们的构想啦。
打开config目录下,在index.js文件,在开发环境里,官方提供了 proxyTable 这个配置项,在这里作些配置,就能够咱们刚才的想法。
proxyTable: {
'/api' : {
target: 'http://localhost:8081',
pathRewrite: {
'^/api': '/static/mock'
}
}
}
复制代码
当咱们去请求api这个目录的时候,咱们但愿它把请求转发到当前这台服务器的端口号上,而后对路径进行替换。 如何替换? 一旦你请求的地址是以 api 开头的,就替换请求到本地的static路径下的mock这个文件夹下。当你去访问api下面的index.json的时候,在开发环境中,vue-cli脚手架工具会自动帮助你把api 替换成/static/mock。
(提示:当我更改了webpack配置项的时候,记得重启服务器,ctr c npm run start)
八.轮播借助第三方的轮播插件 vue-awesome-swiper
安装(npm)
npm install vue-awesome-swiper@2.6.7 --save复制代码
使用(全局引入)
import VueAwesomeSwiper from 'vue-awesome-swiper'复制代码
import 'swiper/dist/css/swiper.css'复制代码
Vue.use(VueAwesomeSwiper)复制代码
在template中使用能够查看官网文档。
<!-- The ref attr used to find the swiper instance -->
<template>
<swiper :options="swiperOption" ref="mySwiper" @someSwiperEvent="callback">
<!-- slides -->
<swiper-slide>I'm Slide 1</swiper-slide> <swiper-slide>I'm Slide 2</swiper-slide>
<swiper-slide>I'm Slide 3</swiper-slide> <swiper-slide>I'm Slide 4</swiper-slide>
<swiper-slide>I'm Slide 5</swiper-slide> <swiper-slide>I'm Slide 6</swiper-slide>
<swiper-slide>I'm Slide 7</swiper-slide> <!-- Optional controls --> <div class="swiper-pagination" slot="pagination"></div> <div class="swiper-button-prev" slot="button-prev"></div> <div class="swiper-button-next" slot="button-next"></div> <div class="swiper-scrollbar" slot="scrollbar"></div> </swiper> </template> <script> export default { name: 'carrousel', data() { return { swiperOption: { // some swiper options/callbacks // 全部的参数同 swiper 官方 api 参数 // ... } } }, computed: { swiper() { return this.$refs.mySwiper.swiper } }, mounted() { // current swiper instance // 而后你就可使用当前上下文内的swiper对象去作你想作的事了 console.log('this is current swiper instance object', this.swiper) this.swiper.slideTo(3, 1000, false) } } </script>复制代码
当轮播图ajax数据获取完成后,swiperList变成真正的数据项。再传给HomeSwiper组件的时候,组件才获取到数据,而后从新渲染出来。由于swiper的初始化建立是根据空数组建立的,因此默认显示的是全部轮播图的最后一项。
解决办法:swiper的初次建立让完整的数据来建立,而不是由空数组建立。只需 添加v-if="list.length" ,当传递过来的list是空数组的时候,v-if为false,因此swiper不会被建立。只有真正的数据过来的时候,swiper才会被建立。
其实这样写是不优雅,模板代码尽可能不要写逻辑。因此能够添加一个计算属性
computed: {
showSwiper () {
return this.list.length
}
}
复制代码
//一些css须要注意的点
防止轮播图加载过程当中下方内容的抖动,能够给<swiper>包裹一层div,而且设置样式
宽高占比
.wrapper
overflow: hidden
width: 100%
height: 0
padding-bottom: 31.25%
background: #eee
复制代码
样式穿透,wrapper样式下的全部swiper-pagination-bullet-active样式 不受 scoped 限制。
.wrapper >>> .swiper-pagination-bullet-active
background: red !important复制代码
当文字不少,空间又不足,显示省略号
ellipsis()
overflow: hidden
white-space: nowrap
text-overflow: ellipsis复制代码
一像素边框颜色不明显
.border-topbottom
&:before
border-color: #ccc
&:after
border-color: #ccc
复制代码
.border-topbottom 这个类的 bofore 和 after 伪元素的border-color 都设置为 #ccc,而经过控制这个颜色,就能够控制页面上一像素边框的颜色。
渐变
background-image: linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,8))复制代码
九.Better-scroll的使用
better-scroll 安装
npm install better-scroll --save复制代码
想要使用 better-scroll 元素须要符合以下dom结构
<div class="wrapper">
<ul class="content">
<li>...</li>
<li>...</li>
...
</ul>
<!-- you can put some other DOMs here, it won't affect the scrolling --> </div>复制代码
使用
import BScroll from 'better-scroll'
const wrapper = document.querySelector('.wrapper')
const scroll = new BScroll(wrapper)复制代码
十.兄弟组件联动
兄弟组件是非父子组件,非父子组件传值可使用 bus总线 形式进行传值。
可是咱们这个兄弟组件比较简单,当咱们处理兄弟组件的时候,可让 Alphabet组件的数据传递给City组件,City组件再转发给List组件。
点击的联动(点击城市列表页的右侧字母表,左侧的列表会自动地滚动到页面的显示区域之中)点击触发事件右侧字母子组件,获取字母(e.target.innerText),并经过$emit方法触发change事件 将字符传给City父组件,父组件获取到字母后,又经过属性传值给城市列表子组件,城市列表子组件经过监听字母地变化,获取字母的dom节点,经过better-scroll的scrollToElement实现自动地滚动。
滚动的联动(滑动城市列表页的右侧字母表,左侧的列表会自动地滚动到页面的显示区域之中) 定义一个标识位,手指触摸的时候标识位位true,结束滑动的时候标识位为false。只有再标识位为true的状况下,才去作move事件的处理。咱们得知道往下滑动的时候,你如今所在的位置是第几个字母。思路是这样的:首先得到首字母A距离顶部的高度,再得到滑动时当前手指距离顶部的高度,作差值就能算出当前手指位置与首字母A的距离,再除以每一个字母的高度,就能知道当前滑动的是第几个字母了。而后去取对应的字母,触发change事件给外部,剩余同上。
十一.列表切换性能优化
当咱们手指在字母表上滑动的时候,就会触发handleTouchMove()事件,可是这样写性能会比较差。
handleTouchMove (e) {
if(this.touchStatus) {
const startY = this.$refs['A'][0].offsetTop
const touchY = e.touches[0].clientY - 79
const index = Math.floor((touchY - startY) /20)
if(index >= 0 && index < this.letters.length ) {
this.$emit('change', this.letters[index])
}
}
}
复制代码
首先,A的offsetTop值是固定的,而咱们须要每次执行这个方法的时候(滑动字母),都会去运算一次 A到顶部的高度。为了提升性能,咱们能够用updated 生命周期钩子,当页面数据被更新的时候,同时页面完成了本身的渲染以后,updated这个钩子就会执行。
updated () {
this.startY = this.$refs['A'][0].offsetTop
}
复制代码
当初次渲染字母组件的时候,是用空对象cities渲染的,当ajax获取到数据以后,cities的值才发生变化,字母组件才被渲染出来。当网字母组件传的数据发生变化的时候,字母组件就会从新渲染。当字母组件从新渲染以后,updated这个生命周期钩子就会被执行,这个时候字母组件就展现了字母的全部内容,这个时候去获取A到顶部的高度。
函数节流
当咱们鼠标或者手指在字母表来回移动的时候,touchmove执行的频率是很是高的。咱们能够经过节流限制函数执行的频率。
handleTouchMove (e) {
if(this.touchStatus) {
if(this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
const touchY = e.touches[0].clientY - 79
const index = Math.floor((touchY - this.startY) /20)
if(index >= 0 && index < this.letters.length ) {
this.$emit('change', this.letters[index])
}
}, 16)
}
}
复制代码
若是你已经正在滑动,让其延迟16毫秒再去执行,假设在16毫秒之间,又作了手指的滚动,那么就会把上一次要作的操做清除掉,从新执行此次要执行的事情。
十二.使用Vuex实现数据共享(首页和城市选择页的数据共享)
Home.vue与City.vue 没有公用的父级组件,这样的话城市页面和首页进行数据传递就没办法经过一个父级的组件进行数据的中转。那该如何进行这两个页面的数据通讯呢?这里咱们可使用BUS总线的方法,可是依然比较麻烦。Vue的官方提供了一种工具,叫作vuex。这是官方推荐的一个数据框架。在vue的大型项目开发之中,vue只能承担视图层的主要内容,当咱们涉及到大量数据之间传递的·时候,每每须要数据框架进行辅助。
如何使用vuex 数据层框架
Vuex指的是整个项目虚线部分的内容。那Vuex是什么呢,当咱们的项目中各个页面或者多个组件之间进行复杂的数据传值很困难的时候,若是可以把公用的数据放到一个公共的存储空间进行存储,而后某一个组件改变了公共的数据,其余组件就能感知到。Vuex的设计理念就是这样的。
上图中,Vuex虚线部分就是一个公用数据存储区域,能够理解为是一个仓库。仓库中有一个State区域,全部的公用数据都存放在State之中,那组件若是想用一个公用的数据,直接去调用State 就能够了。有的时候咱们想改变State里的数据,(不能让组件直接去改变数据)流程是这样的:若是有异步操做,就把异步操做放在Actions里,或者一些比较复杂的批量的同步操做也能够放到Actions里。组件先去调用Actions,Actions紧接着去调用Mutations,Mutations里面放的是一个一个同步地对State的修改。固然这也不是绝对的,有的时候可让组件直接去调用Mutations去修改State里面的数据。须要注意的是,当组件调用Actions的时候,调用的是一个Dispatch()方法来操做Actions,Actions或者组件调用Mutations的时候须要用到Commit()方法。
安装vuex
npm install vuex --save复制代码
直接在main.js中引入vuex使用vuex,这样作其实不太好,vuex要作的文件夹实际上是比较复杂的。因此,单独在src目录下建立一个store文件夹,而后再store文件夹创建一个index.js的文件。
vuex是一个插件,vue里面使用插件都是经过Vue.use( )使用的。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store ({
state: {
city: '北京'
}
})复制代码
而后在入口文件main.js中引用
import store from './store'
复制代码
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
复制代码
这样就能够在各个组件中使用啦
<div>
{{this.$store.state.city}}
</div>复制代码
如今咱们想经过点击“热门城市”来改变“当前城市”,就是公用城市也要跟着变化,那该怎么作呢?(改变state)
首先须要调用Actions而后再去调用Mutations。
在list组件中点击热门城市改变city的时候,经过dispatch()方法调用 actions,传递两个参数,分别是'changeCity' 这个actions和 要改变的city
handleCityClick(city) {
this.$store.dispatch('changeCity',city)
}
复制代码
在store中建立一个actions对象,接受到dispatch过来的一个‘changeCity’方法,接受两个参数分别是上写文ctx和传递过来的数据city。actions要经过commit来调用mutations,mutations来改变数据。
export default new Vuex.Store ({
state: {
city: '北京'
},
actions: {
changeCity (ctx,city) {
ctx.commit('changeCity',city)
}
},
mutations: {
changeCity (state,city) {
state.city = city
}
}
})复制代码
以上步骤改变State的过程里并无任何的异步操做,也不是批量操做,因此这个时候组件不必去调用Actions ,组件能够直接去调用Mutations。
handleCityClick(city) {
this.$store.commit('changeCity',city)
}
复制代码
export default new Vuex.Store ({
state: {
city: '北京'
},
mutations: {
changeCity (state,city) {
state.city = city
}
}
})复制代码
十三.Vuex的高级使用及localStorage
html5中引入了一个新的API localStorage ,能够帮助咱们实现cookie的功能,作到本地存储。在这里咱们用localStorage完成城市保存的功能。
须要注意的是:当你使用localStorage,建议就在外层包裹一个try catch。由于在某些浏览器,若是用户关闭了本地存储这样的功能,或者选择隐身模式,你使用localStorge有可能会致使浏览器直接抛出异常,致使代码没法运行。
try{
localStorage.city = city
} catch (e) {}
复制代码
let defaultCity = '上海'
try {
if(localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {}
复制代码
这样写代码,就比较规范了。
此时store下的index.js变得复杂起来了。为了易读性和可维护性,咱们能够对代码进行拆分。怎么拆分这里就很少说啦。
有的时候由于城市名的长度,首页header组件样式会被破坏。
.header-right
width: 1.24rem
float: right
text-align: center
color: #fff
.arrow-icon
margin-left: -.04rem
font-size: .24rem复制代码
这里咱们设置一个左右的padding,将width改成min-width就能够啦
.header-right
min-width: 1.04rem
padding: 0 .1rem
float: right
text-align: center
color: #fff
.arrow-icon
margin-left: .04rem
font-size: .24rem复制代码
Vuex的高级用法:(代码优化)
{{this.$store.state.city}}
复制代码
这时候咱们使用公用数据,须要经过 {{this.$store.state.city}} 这样一长串才能获取到咱们要的city数据。
Vuex中提供了一个比较高级的API,
首先咱们引入mapState
import { mapState } from 'vuex'复制代码
以后咱们来一个计算属性
computed: {
...mapState(['city'])
}
复制代码
...mapState(['city']) 把vuex里面的city共用数据映射到该组件的名叫city的computed计算属性里。作好映射后,就能够 用 {{this.city}} 来获取city数据了。
传递内容能够是个数组,也能够是个对象。
computed: {
...mapState({
currentCity: 'city'
})
}
复制代码
映射后的计算属性名字就叫 currentCity 啦。因此咱们经过 {{this.currentCity}}来获取数据。
handleCityClick(city) {
this.$store.commit('changeCity',city)
this.$router.push('/')
}
复制代码
当咱们点击城市按钮的时候,会经过commit方法 派发一个mutations,Vuex一样提供了一个简便的API mapMutations
一样使用引入mapMutations
methods: {
handleCityClick(city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
复制代码
有一个mutations叫作changeCity,而后把这个mutations映射到组件里的一个叫作changeCity方法里,咱们调用mutations就能够直接调用cahngeCity()这个方法啦。
Vuex有几个核心的概念,state存放公用数据,actions用于写些异步方法或者同步批量操做,mutations用于写些同步地对数据地改变。Vuex中还提供了 getters API,他的做用有点相似于组件中的computed计算属性的做用,当咱们须要根据 state 里面的数据算出一些新的数据就能够借助 getter 来提供新的数据,避免数据的冗余。
getters: {
doubleCity (state) {
return state.city + ' ' + state.city
}
}复制代码
computed: {
...mapGetters(['doubleCity'])
}复制代码
当咱们遇到一个很是复杂的业务场景,好比说咱们在管理后台系统的时候,常常会有不少公用的数据在vuex里面进行存储,这样mutations文件会变得很是庞,难以维护。这个时候能够借助module对一个复杂的state,mutations,actions进行拆分。建立store的时候能够经过module来对store的建立。
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态复制代码
这样作,A模块只要存储和A模块相关的数据和数据的操做就能够了,而后在建立store时候再对各个模块的数据进行整合。
十四. 使用keep-alive优化网页性能
咱们打开chrome 下的Network 切换到XHR,会发现咱们切换一次页面就会请求一次数据,缘由是每次路由切换到一个组件的时候,这个组件就会被从新渲染,它的mounted()钩子就会被执行,那么ajax数据就会从新获取。这样每次切路由都从新获取一次数据会大大的下降性能。
咱们只要在App.vue这个项目根组件的路由 <router-view/> 外包裹<keep-alive>
<keep-alive>
<router-view/>
</keep-alive>
复制代码
这样,路由的内容被加载过一次后就把路由的内容放到内存中,下一次再进这个路由的时候,不须要从新渲染这个组件,只须要去取内存中内容显示就能够啦。
这个时候其实咱们代码还存在一些问题,当咱们选择城市后,再路由到首页后,首页的内容是不会变化的。
咱们能够经过vuex,将ajax请求路径为相应城市
axios.get('/static/mock/index.json?city=' + this.city)复制代码
可是,由于我App.vue路由中添加了keep-alive 后,就算选择了不一样的城市,页面也不会被从新渲染了。
那咱们如何去改变缓存里的数据呢?方法1:当咱们使用keep-alive的时候,组件里会多出一个生命周期函数activated()(keep-alive 组件激活时调用activated),当页面从新被显示的时候执行activated,在activad()里判断选择的城市是否被改变,改变了就从新发送ajax请求。
方法2:加个exclude,这个组将就不会进行缓存了。
<keep-alive exclude="Detail">
<router-view/>
</keep-alive>
复制代码
十五.动态路由
path: '/detail/:id'
vue中路径后加 :id 为动态路由
十六.对全局事件的解绑
在上一节中,咱们对window作了事件的绑定
activated () {
window.addEventListener('scroll', this.handleSroll)
}
复制代码
若是,咱们在某个组件的标签上绑定了某个事件,只做用于这个组件,不会对外部组件产生任何的影响。可是,在这个组件里写的是对window这个全局事件的绑定,在该页面关闭时就须要对其解绑。那如何解绑呢?当我i们对这个组件用了keep-alive的时候,组件会提供 activated 生命周期钩子,在每次页面展现的时候被执行。与之对应,还提供了一个叫 deactivated生命周期钩子,在页面即将被隐藏,或者即将被替换成其余页面的时候,deactivated就会被执行。
deactivated () {
window.removeEventListener('scroll', this.handleSroll)
}
复制代码
也就是,页面展现的时候绑定scroll事件,页面被隐藏的时候,对scroll事件解绑。
十七.使用递归组件实现详情页列表
每一个组件的 name 的做用是什么?
1.当咱们作递归组件的时候,会用到name
<template>
<div>
<detail-list></detail-list>
</div>
</template>
export default{
name: 'DetailList'
}复制代码
2.当咱们在也页面上想对某个页面取消缓存的时候
<keep-alive exclude="Detail">
<router-view/>
</keep-alive>复制代码
3.vue-devtool调试