记录学习点滴
minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"
阻止用户手滑发大缩小页面
npm install fastclick --save
import fastClick from 'fastclick'
fastClick.attach(document.body)
npm install stylus --save
npm install stylus-loader --save
import './assets/styles/iconfont.css'
iconfont
类名,就可以在页面中使用 >图标了,可以用每一个图标类名来引用,也可以使用编码的形式来使用,每一个图标的编码
都在 iconfont官网我的项目图标里面,点击复制图标就能得到图标编码;有些代码的样式是多变的,我们可以将可变的css放入assets styles文件夹的varibles.styl文件中,方便以后的更爱–》改一处全部就改的效果
例如:我们的背景色就是一个可改变的css参数,我们可以在varibles.styl中定义 bgcolor = #00bcd4 背景色而后在样式里引入这个styl文件即可@import '../../../assets/styles/varibles.styl';background-color bgcolor
但是@import文件引入的前缀非常长,在可以使用@符号可以优化此问题
因为我们在webpack配置js文件中制定'@': resolve('src'),
制定了@就是src目录
但是我们在css中引入css文件是 需要使用src的时候 要在@前面再多加一个~符号
相同的 我们的sytles文件夹多次使用 我们可以在webapck.config.js文件中定义
'styles': resolve('src/assets/styles'),
这样我们使用styles目录的时候就可以简化了
在企业级的开发里,每一个新功能或新模块的开发都是在一个新的分支上进行 开发完成后再合并到master主分支上
在github上创建仓库:
Create a new repository on the command line
touch README.md
git init
git add README.md
git commit -m "first commit"
git remote add <name> <url>
git push -u origin master
在本地新建一个分支: git branch Branch1
切换到你的新分支: git checkout Branch1
将新分支发布在github上: git push origin Branch1
在本地删除一个分支: git branch -d Branch1
在github远程端删除一个分支: git push origin :Branch1 (分支名前的冒号代表删除)
$ git branch
* master
git branch -r
git branch -a
git branch [branch name]
git checkout [branch name]
git checkout -b [branch name]
git checkout -b [branch name] 的效果相当于以下两步操作:
git branch [branch name] + git checkout [branch name]
git push origin [branch name]
orgin是你远程仓库的名字git branch -d [branch name]
git push origin :[branch name]
分支名前的冒号代表删除。git checkout master
git merge <name>/<new-branch-name>
git push
首页轮播图,采用vue-awesome-swiper插件
npm装包
npm install vue-awesome-swiper@2.6.7 --save
使用方法和使用步骤参考官网
在swiper-slide标签里填入img属性并引入src 加入类swiper-img 在style里定义width的宽度为100% 即可适应轮播
此时的页面在网速不好的情况下会发生页面抖动 如何解决 在轮播元素的最外层加一个class为wrapper的div 然后定义.wrapper的样式
.wrapper
overflow hidden
width 100%
height 0
padding-bottom: 26.67%
background #eee
.swiper-img
width 100%
这样就能把轮播图的位置保持撑起,就不会发生页面抖动了
此时,又有一个问题,我们需要导航点,怎么实现
swiperOption: {
pagination: '.swiper-pagination'
}
在swiperOption里添加pagination配置项就可以了
此时的导航激活状态是蓝色的 怎么更改为白色? 我们可以在页面查看小原点的类名为
swiper-pagination-bullet-active
,我们如果直接在样式中修改这个样式的background,是达不到更改效果的,为什么,因为此时的样式是当前组件的样式,而这个小圆点属于swiper组件的样式 这时,我们可以使用穿透样式来实现 在样式的最前面编写如下代码
.wrapper >>> .swiper-pagination-bullet-active
background: #eee
这样,就能达到从一个组件穿刺到另一个组件的样式更改
最后 使用v-for 对图标进行列表渲染循环,把数据保存到data的swiperList对象中
初始化
图标区域逻辑实现
当页面图标大于八个 可以左右拖动
vue官方推荐使用axios来完成ajax数据的请求
npm install axios --save
如果每个子组件都发送一个ajax请求来获取数据的话,一个首页就要请求多个ajax请求,会使我们的程序效率下降,我们可以在home组件请求一个ajax请求,把数据传给子组件,这样就能提高效率
怎么模拟后台的数据呢?
因为我们页面整直接访问static文件夹,所以我们可以在static下创建一个mock文件夹,里面定影json文件来模拟后台数据
但是我们并不想提交我们的数据到github,所以我们可以在gitnore文件中排除文件
我们上线后的ajax请求地址都是基本都是相对路径’/api/下的json文件,但是此时我们的文件在static/mock文件夹中,我们可以把axios的请求地址改成我们本地的static/mock,但是这样做的话以后上线前要更改代码,这是不可取的
即使用api文件目录,又能获取到static中的文件,怎么办?
我们可以使用vue基于webpack-dev-serve的一个配置选项来解决这个问题,在vuecli生成的config文件夹中index.js文件有一个proxyTable
配置选项
我们可以这样来替换我们的请求地址:
proxyTable: {
'/api': {
target: 'http://localhost:8080',
pathRewrite: {
'^/api': '/static/mock'
}
}
}
这样,就能完美解决我们的问题了
注意,json格式的每一项的最后一项不要加带分号,这样可能会导致json数据解析失败
由于home组件获取json数据后,应该向子组件传递数据,这就涉及到父组件向子组件传值的问题 父组件通过属性向子组件传值,子组件props接受数据
methods: {
getHomeInfo () {
axios.get('/api/index.json') // 返回的是一个promise对象,后面使用then
.then(this.getHomeInfoSucc) // 获取成功执行getHomeInfoSucc函数
},
getHomeInfoSucc (res) {
res = res.data
if (res.ret && res.data) {
const data = res.data
this.city = data.city
this.swiperList = data.swiperList
this.iconList = data.iconList
this.recommendList = data.recommendList
this.weekendList = data.weekendList
}
console.log(res)
}
},
mounted () {
this.getHomeInfo() // 页面挂载好执行这个方法ajax获取数据
}
title聊表的边框不太明显,可以给其添加样式
.border-topbottom
&:before
border-color #ccc
&:after
border-color #ccc
因为我们将要使用一个滚动插件–Better-scroll来完成此页面,所以我们应该禁止页面的超出滚动
.list
overflow hidden
position absolute
top 1.58rem
left 0
right 0
bottom 0
使用Better-scroll
因为这个组件需要最外城的wrapper dom元素 我们给最外层标签添加ref=”wrapper”属性
使用flex布局使其居中
Todo1. 点击右侧字母表 list也跳到对应的城市也部分
循环字母列表时为每一个字母绑定点击事件 alphabet组件传递消息给父组件city,city在传递消息给list组件,实现Alphabet和list的兄弟传值
@click="handleLetterClick"
handleLetterClick (e) {
this.$emit('change', e.target.innerText)
},
@change="handleLetterChange"
handleLetterChange (letter) {
this.letter = letter
}
:letter="letter"
传递给list.vue组件
watch: {
letter () { // 监听letter改变
if (this.letter) {
const element = this.$refs[this.letter][0]
// refs-->通过为每个循环绑定ref ref的值对应的是每个key 也就是每个字母
// [0]-->取到的是一个数组,具体的元素dom节点为数组的第一项
this.scroll.scrollToElement(element)
// scroll插件的而一个方法帮我们调到制定元素
}
}
}
Todo2. 滑动右侧字母表,list跟着滑动到对应的位置
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchEnd="handleTouchEnd"
把字母表从cities获取放到计算属性letters中
computed: {
letters () {
const letters = []
for (let i in this.cities) {
letters.push(i)
}
return letters
// ['A','B','C'...]
}
},
将计算出的滑到哪个字母$emit传递给父元素
handleTouchMove (e) {
if (this.touchStatus) {
const startY = this.$refs['A'][0].offsetTop // A元素距离顶部的高度
const touchY = e.touches[0].clientY - 79 // 手指距离header下边缘的的距离
const index = Math.floor((touchY - startY) / 22) // 滑动了第几个字母
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index])
}
// console.log(index)
}
},
:letter="letter"
传递给list
同样的和1一样使用watch来监视Todo3. 列表组件优化
const startY = this.$refs['A'][0].offsetTop
startY的值是固定的,可以提取出来放在updated生命周期函数钩子中,因为刚开始加载citise是通过json获取的,刚开始获取不到的时候是空,之后有获取到了ajax的内容,页面更新,就会执行updated钩子函数
handleTouchMove (e) {
if (this.touchStatus) {
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
const touchY = e.touches[0].clientY - 79 // 手指距离header下边缘的的距离
const index = Math.floor((touchY - this.startY) / 22) // 滑动了第几个字母
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index])
}
// console.log(index)
}, 10)
}
}
<div class="search-content" ref="search" v-show="keyword">
<ul>
<li
class="search-item border-bottom"
v-for="item of list"
:key="item.id"
>
{{item.name}}
</li>
<li class="search-item border-bottom" v-show="hasNoData">
没有找到匹配数据
</li>
</ul>
</div>
ref = search 用于在mounted挂载滚动插件 v-show=”keyword” 没有输入内容不显示
我们想要城市页面和首页实现数据共享 City.vue和Home.vue是没有一个父组件可供中转,那么想进行两者的通信,该怎么办呢?
Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({ // 向外暴露一个由Actions State Mutations 三个组成的系统对象
state: {
city: 'aaa'
},
// actions: {
// changeCity (ctx, city) { // 借助这个ctx上下文来使用commit方法来调用Mutations完成数据的更改
// console.log(city)
// console.log(ctx)
// ctx.commit('MchangeCity', city)
// }
// },
mutations: {
MchangeCity (state, city) {
state.city = city
}
}
})
import store from './store' // vuex
这样我们全局都能访问到store了
并在vue实例中申明store,这样,我们以后就能使用vuex的数据了
{{this.$store.state.city}}具体使用
{{this.$store.state.city}}
@click="handleCityClick(item.name)
并在methods中定义方法: methods: {
handleCityClick (city) {
this.$store.commit('MchangeCity', city) // 想要通过actions调用方法必须使用dispatch 或者 跳过actions直接通过commit来调用Mutations
this.$router.push('/') // 选择后跳转到主页 实现联动 用了vue-router的编程跳转链接
}
}
总结:
想要通过vuex来管理公用数据,想要更改数据 要经过一下步骤
methods: {
handleCityClick (city) {
this.$store.dispatch('changeCity', city) // 想要通过actions调用方法必须使用dispatch
}
actions: {
changeCity (ctx, city) { // 借助这个ctx上下文来使用commit方法来调用Mutations完成数据的更改
ctx.commit('MchangeCity', city)
}
},
mutations: {
MchangeCity (state, city) {
state.city = city
}
}
在不复杂的环境下,有的时候我们更爱数据并不一定需要经过Actions,组件可以直接通过commit来使Mutations改变State
methods: {
handleCityClick (city) {
this.$store.commit('MchangeCity', city) // 想要通过actions调用方法必须使用dispatch
}
mutations: {
MchangeCity (state, city) {
state.city = city
}
}
上述我们已经完成了vuex 实现两个不先练的组件的数据共享,但是我们一旦刷新我们的页面,我们的页面数据还是默认的我们在store中定义的数据,如何让程序记录我们的操作
使用localStorage来完成
在Mutations定义的方法里 加入:
localStorage.city = city
来记录我们选择的城市
在state中
city: localStorage.city || '南阳'
这样 浏览器就能记忆我们选择的城市了
但是此时存在一个问题,浏览器如果使用了隐身模式或者关闭了浏览器存储,我们的程序就会直接报错无法执行 我们可以使用try catch来优化一下我们的代码
vuex高级
路由发生切换的时候 ajax都会被重新发送,为什么?
因为我们的页面每一次渲染都会执行mounted钩子 而我们的ajax请求就是放在mounted中进行的
怎么优化?
将我们的router-view坑用keep-alive标签包裹起来
<template>
<div id="app">
<keep-alive>
<router-view/>
</keep-alive>
</div>
</template>
页面被keep-alive包裹起来,就会是页面的资源加载到内存当中,不需要重新渲染,也不需要从新执行钩子,来回返回页面也只会获取一次json
此时,我们的vue中多出来一个生命周期函数钩子:activated
我们之前写的代码是固定的,虽然选择的城市发生变化,但是我们的我们的home页面中的内容并没有变化,怎么办?
我们home首页的内容是有index.json ajax来获取的 我们只需要在home组件获得ajax的时候 使用?传参的方式,使得每一个城市对应自己的json文件,就可以了
axios.get('/api/index.json?city=' + this.city
但是此时的json文件被缓存到了内存当中,存的还是第一次的值,我们怎么改变缓存的数据呢
由于此时的页面被keep-alive标签包裹,我们的ajax请求只会在第一次刷新的时候被获取,但是此时我们需要由城市列表选择的城市来同步我们首页的json文件以达到统一刷新的目的
keep-detail 可以加入exclude=”不被缓存的组件名字” 这样就可以指定排除某个组件不被缓存
此时我们可以使用activated生命周期钩子
因为在被包裹keep-alive标签之后,mounted钩子不会执行,但是activated钩子只要页面重新出现,就会执行,所以我们可以在activated钩子函数中 判断页面选择的城市和之前的城市是否为一个城市,如果不是一个城市,则重新发送ajax请求
我们在data数据中新增一个 lastcity
数据 配合activated
钩子使用
activated () {
if (this.lastcity !== this.city) {
this.lastcity = this.city
this.getHomeInfo()
}
}
创建detail.vue Banner.vue 导入detail路由
background-image linear-gradient
达到渐变效果这个画廊组件不仅仅这个组件中要使用,以后可能在别的地方也会使用
所以我们新建 src/common/gallary/Gallary.vue 编写画廊组件为以后复用
observeParents: true
和 observer: true
observeParents: 将observe应用于Swiper的父元素。当Swiper的父元素变化时,例如window.resize,Swiper更新。
observer: 启动动态检查器(OB/观众/观看者),当改变swiper的样式(例如隐藏/显示)或者修改swiper的子元素时,自动初始化swiper。window.addEventListener('scroll', this.handleScroll)
来监听滚动的距离以切换哪个头部的展示 这个方法放在activated
钩子里展示效果做好,剩下渐隐渐显的效果
在 fixed 的头部标签绑定样式对象 :style="opacityStyle"
handleScroll () {
const top = document.documentElement.scrollTop
if (top > 60) { // 过渡阶段
let opacity = top / 140 // 过渡效果
opacity = opacity > 1 ? 1 : opacity
this.opacityStyle = { opacity }
this.showAbs = false
} else {
this.showAbs = true
}
}
}
我们在5.3中,使用 window.addEventListener('scroll', this.handleScroll)
来监听滚动的距离,但是这个监听方法被绑定在了全局window中,所以我们的其他页面滚动时也会执行这段代码
那么 我们怎么样才能使其只绑定在详情页呢?
当我们使用keep-alive标签的时候,activated钩子函数产生的同时,也产生了一个deactivated的函数钩子,在activated绑定,在deactivated解绑即可
activated () {
window.addEventListener('scroll', this.handleScroll) // 页面展示绑定
},
deactivated() {
window.removeEventListener('scroll', this.handleScroll)
}
组件自生调用自己
我们发现,首页滑动到底部,在点击详情页面,详情页面初始状态也是在底部,怎么办?
页面滑动 各个组件会相互影响,我们可以在路由的配置选项中添加如下配置:
scrollBehavior: function (to, from, savedPosition) {
return savedPosition || { x: 0, y: 0 }
}
每个组件的export defalut的name是干什么用的?
我们目前接触到的:
我们之前都是自己模拟后端的数据,实际项目中,我们是要和后端的数据,实现项目联调,如何进行?
把mock中的数据替换成真正的后端服务器数据
把config index.js 中的api制定的路径改为后端服务器的地址 一般都是本地80端口,一般是一下的形式
proxyTable: {
'/api': {
target: 'http://localhost:80'
}
}
我们的项目是 通过 Webpack dev server 来进行的 它默认不支持ip地址的访问方式,要把它的默认配置项修改
在package.json下 修改dev配置项 webpack-dev-server --host 0,0,0,0
这样,就可以直接通过手机用ip地址来访问我们的项目
在真机上,我们拖动字母表,会发现整个页面都跟着滚动,出现了bug,怎么半?
@touchstart.prevent="handleTouchStart"
组织拖动的默认行为
在低版本的安卓浏览器,可能出现白屏现象,怎么办?
出现白屏现象的原因大部分是因为手机浏览器不支持promise特性,我们在项目中安装一个第三方的包
npm install babel-polyfill --save
import 'babel-polyfill'