使用fastclick包減少移動端觸動div元素時的3ms延遲
import fastclick from 'fastclick';
fastclick.attach(document.body);
圖片懶加載
//使用vue-lazyload第三方插件
npm i vue-lazyload -s
//main.js
import vueLazyload from 'vue-lazyload'
Vue.use(vueLazyload)
抽離普通組件
在移動端中像banner圖,滑動組件和加載組件等這些基礎組件可以抽離為子組件。利用props和slot將父組件中的數(shù)據(jù)和模板傳遞給子組件。
<div>
<slot><slot> //子組件中使用slot標簽,可以將父組件中把子組件包裹的標簽傳遞給子組件
<div>
//子組件
<script>
export default{
props:{
data:'',
}
}
</script>
//父組件
<子組件 :data='123'></子組件> //如此就將父組件的data相對于的傳給了子組件中props的data中。
重復性的數(shù)據(jù)聚合可以另外封裝一個類
//這個類把繁瑣的avatar聚合過程封裝成了類
export default class Singer {
constructor({id, name}) {
this.id = id
this.name = name
this.avatar = `https://y.gtimg.cn/music/photo_new/T001R300x300M000${id}.jpg?max_age=2592000`
}
}
//類中的構造函數(shù)需要傳兩個參數(shù)
var singer = new Siner({
name:'123',
id:'123'
})
eslint下的paops的array屬性
其中的default如果設置為[]會報錯,需要()=>[]才不會報錯
es6的sort和map方法
// 3.將字母用sort方法,將title的charcodeat進行比較排序
ret.sort((a, b) => {
return a.title.charCodeAt(0) - b.title.charCodeAt(0)
})
//map方法就是將本數(shù)組進行遍歷修改后賦值給新數(shù)組
shortcutList() {
return this.data.map((group) => {
return group.title.substr(0, 1)
})
}
dom的attribute方法
是在dom元素中添加和獲取屬性的值,如id type class name等等屬性,也可以自定義屬性名
function getData(el, name, val) {
const prefix = 'data-'
name = prefix + name //自定義屬性名
if (val) {
return el.setAttribute(name, val) //在el的dom元素添加設置name屬性值val
} else {
return el.getAttribute(name) //獲取el的dom元素值
}
}
vue數(shù)據(jù)的響應
在vue的data,props和computed等屬性中創(chuàng)建的變量都會自動創(chuàng)建get,set等方法來監(jiān)聽數(shù)據(jù)的變化,來達到數(shù)據(jù)的響應。如果有些數(shù)據(jù)不需要監(jiān)聽,可以在created屬性中創(chuàng)建。
created(){
this.message={} //這樣就創(chuàng)建了一個message變量,但不會被監(jiān)聽
}
右側導航與主體導航的聯(lián)動
1.首先我們需要實時的檢測滾動到的位置
// 可以使用bscroll插件提供的listenscroll方法監(jiān)聽所處的位置
if (this.listenScroll) {
let me = this
this.scroll.on('scroll', (pos) => {
me.$emit('scroll', pos)
})
}
//使用emit派發(fā)一個事件給父組件,父組件接收
scroll(pos) {
this.scrollY = pos.y //講y位置傳給父組件scrolly值
},
2.將主體的每個導航的位置保存為數(shù)組
_calculateHeight() {
this.listHeight = []
let height = 0
this.listHeight.push(height)
let list = this.$refs.listGroup
for (let i = 0; i < list.length; i++) {
height += list[i].clientHeight
this.listHeight.push(height)
}
}
3.使用watch監(jiān)聽滾動的位置跟主體位置數(shù)組的區(qū)間[i,i+1)進行比較,計算出所處的區(qū)間
watch: {
data() {
setTimeout(() => {
this._calculateHeight()
}, 20)
},
//鑒定scrollY的變化
scrollY(newY) {
const listHeight = this.listHeight
// 拉到最頂部的情況
if (newY > 0) {
this.currentIndex = 0
}
// 在中間部分的情況
for (let i = 0; i < listHeight.length - 1; i++) {
let height1 = listHeight[i]
let height2 = listHeight[i + 1]
if (!height2 || (-newY >= height1 && -newY < height2)) {
this.currentIndex = i
// console.log(this.currentIndex)
return
}
}
// 最底部
this.currentIndex = listHeight.length - 2
}
}
4.將右側導航進行高亮
//判斷位置,動態(tài)添加current樣式
:class="{'current':index == currentIndex}"
vuex
//vuex的常用配置(index.js,state.js,mutations.js,mutation-type.js,getters.js,actions,js)
//vuex提供了許多語法糖,map系列(mapmutation,mapgetters,map...)
//解構賦值出mapMutation方法,進行存數(shù)據(jù)操作
import {mapMutations} from 'vuex'
methods:{
其他的方法(singer){
this.setSinger(singer)
},
...mapMutations({
setSinger: 'SET_SINGER' //對mutations的一個映射
})
//這樣就可以在其他方法中用this.setSinger使用mutation中的SET_SINGER方法
//等同于使用this.$store.commit(SET_SINGER,singer)
}
//解構賦值出mapGetters方法,進行取數(shù)據(jù)操作
import {mapGetters} from 'vuex'
computed:{
...mapGetters([
'singer' //將getters的singer映射掛載到vue實例中
]),
created(){
console.log(this.singer) //就可以使用this.singer取到getter中singer的映射了
}
}
promise
//promise的用法,先新建一個promise方法,將異步方法放進里面,resolve出你要的值,這里axios是一個異步方法
function getSongUrl(id) {
return new Promise((resolve, reject) => {
axios.get('/song/url?id=' + id).then(res => {
// console.log(res.data.data[0].url)
resolve(res.data.data[0].url)
})
})
}
//然后,asnyc 一個函數(shù)里面,await上面的函數(shù),url總是獲取不到,是因為在初始化的時候,getSongUrl已經運行完了
export async function createSongs(musicData) {
return new Song({
id: musicData.id,
singer: filterSinger(musicData.ar),
name: musicData.name,
album: musicData.al.name,
duration: musicData.l.size,
image: musicData.al.picUrl,
url: await getSongUrl(musicData.id)
})
}
//這樣就把createSongs方法定義成了一個promise方法,這樣就能取到它的url值,直接調用createSongs,用.then處理promise回來的數(shù)據(jù)
_normalizeSongs(list) {
list.forEach(item => {
// ret.push(createSongs(item).then(data => data))
createSongs(item).then(data => this.songs.push(data))
})
}
自定義prefixStyle根據(jù)瀏覽器添加樣式前綴
let elementStyle = document.createElement('div').style
let vendor = (() => {
let transformNames = {
webkit: 'webkitTransform',
Moz: 'MozTransform',
O: 'OTransform',
ms: 'msTransform',
standard: 'transform'
}
for (let key in transformNames) {
if (elementStyle[transformNames[key]] !== undefined) {
return key
}
}
return false
})()
export function prefixStyle(style) {
if (vendor === false) {
return false
}
if (vendor === 'standard') {
return style
}
return vendor + style.charAt(0).toUpperCase() + style.substr(1)
}
//使用自定義prefixStyle
import {prefixStyle} from 'common/js/dom'
const transform = prefixStyle('transform')
const backdrop = prefixStyle('backdrop-filter')
this.$refs.imgheight.style[transform] = `scale(${scale})`
使用create-keyframe-animation插件可以在js使用animation動畫
//導入animation包
import animations from 'create-keyframe-animation'
const animation = {
0:{干嘛干嘛},
60:{干嘛干嘛},
100:{干嘛干嘛}
}
//注冊animation動畫的方法
animations.registerAnimation({
name: 'move',
//動畫樣式
animation,
//基礎設置
presets: {
//持續(xù)時間
duration: 400,
easing: linear //線性動畫
}
})
//將動畫掛載到dom中
animations.runAnimation(this.$refs.cdWrapper,'move',done) //第一個參數(shù)是dom,第二個是動畫名,第三個是結束的回調
//在結束的回調記得將動畫銷毀
animations.unregisterAnimation(‘move')
使用三目運算符和computed屬性改變icon的圖標和動態(tài)改變keyframe動畫
字符串補零的方法
// 其中num為你傳的字符串,n為你要補到的位數(shù)
_pad(num, n = 2) {
let len = num.toString().length
//其中用while是當n>2時的情況所需,‘0’為你要補的字符串,可在前或后補
while(len < n){
num = '0' +num
len++
}
return num //此方法可為前后補字符串用。
}
移動端事件方法
//對于移動端,瀏覽器提供了touchStart,touchMove,touchEnd三個方法
<scroll
@touchStart = 'touchStart'
@touchMove = 'touchMove'
@touchStart = 'touchEnd'
>
//在methods中定義
methods: {
//參數(shù)默認為調用事件的元素
touchStart(e){
let x = e.touchs[0].pageX //e.touches[0],代表點擊的第一個位置,pageX是第一個位置的x坐標
}
......
}
</scroll>
getBoundingClientRect()
getBoundingClientRect用于獲取某個元素相對于視窗的位置集合。集合中有top, right, bottom, left等屬性。

<!
返回值類型:
rectObject.top:元素上邊到視窗上邊的距離;
rectObject.right:元素右邊到視窗左邊的距離;
rectObject.bottom:元素下邊到視窗上邊的距離;
rectObject.left:元素左邊到視窗左邊的距離;
!>
//一般是過去一個元素,然后去調用他對于視窗的距離,進行動態(tài)改變樣式
rectObject = object.getBoundingClientRect();
rectObject.left //這就獲取到元素左邊到視窗左邊的距離
vue中的mixins屬性
<meta charset="utf-8">
minxin其實是一個對象,里面的結構大致跟普通組件的script里面的一樣,有data屬性,鉤子函數(shù)和方法等
混入 (mixins) 是一種分發(fā) Vue 組件中可復用功能的非常靈活的方式。混入對象可以包含任意組件選項。當組件使用混入對象時,所有混入對象的選項將被混入該組件本身的選項。
在實際項目中,可以新建一個js文件,導出一個minxin對象 在引用的組件中引入使用即可
這里例子就簡單的跟官網一樣幫助理解即可
選項合并
當組件和混入對象含有同名選項時,這些選項將以恰當?shù)姆绞交旌稀?/p>
比如,數(shù)據(jù)對象在內部會進行淺合并 (一層屬性深度),在和組件的數(shù)據(jù)發(fā)生沖突時以組件數(shù)據(jù)優(yōu)先。
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
// => { message: "goodbye", foo: "abc", bar: "def" }
}
})
同名鉤子函數(shù)將混合為一個數(shù)組,因此都將被調用。另外,混入對象的鉤子將在組件自身鉤子之前調用。
var mixin = {
created: function () {
console.log('混入對象的鉤子被調用')
}
}
new Vue({
mixins: [mixin],
created: function () {
console.log('組件鉤子被調用')
}
})
// => "混入對象的鉤子被調用"
// => "組件鉤子被調用"
值為對象的選項,例如 methods, components 和 directives,將被混合為同一個對象。兩個對象鍵名沖突時,取組件對象的鍵值對
var mixin = {
methods: {
foo: function () {
console.log('foo')
},
conflicting: function () {
console.log('from mixin')
}
}
}
var vm = new Vue({
mixins: [mixin],
methods: {
bar: function () {
console.log('bar')
},
conflicting: function () {
console.log('from self')
}
}
})
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"