vue的音乐webapp总结

使用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将父组件中的数据和模板传递给子组件。

<div>
<slot><slot>    //子组件中使用slot标签,可以将父组件中把子组件包裹的标签传递给子组件
<div>

//子组件
<script>
export default{
props:{
data:'',
}
}
</script>
//父组件
<子组件 :data='123'></子组件>  //如此就将父组件的data相对于的传给了子组件中props的data中。

重复性的数据聚合可以另外封装一个类

//这个类把繁琐的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`
  }
}
//类中的构造函数需要传两个参数
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方法就是将本数组进行遍历修改后赋值给新数组
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数据的响应

在vue的data,props和computed等属性中创建的变量都会自动创建get,set等方法来监听数据的变化,来达到数据的响应。如果有些数据不需要监听,可以在created属性中创建。

created(){
this.message={} //这样就创建了一个message变量,但不会被监听
}

右侧导航与主体导航的联动

1.首先我们需要实时的检测滚动到的位置

// 可以使用bscroll插件提供的listenscroll方法监听所处的位置
      if (this.listenScroll) {
        let me = this
        this.scroll.on('scroll', (pos) => {
          me.$emit('scroll', pos)
        })
      }
//使用emit派发一个事件给父组件,父组件接收
 scroll(pos) {
      this.scrollY = pos.y  //讲y位置传给父组件scrolly值
    },

2.将主体的每个导航的位置保存为数组

 _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监听滚动的位置跟主体位置数组的区间[i,i+1)进行比较,计算出所处的区间

 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.将右侧导航进行高亮

//判断位置,动态添加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方法,进行存数据操作
 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方法,进行取数据操作
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 一个函数里面,await上面的函数,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回来的数据
    _normalizeSongs(list) {
      list.forEach(item => {
        // ret.push(createSongs(item).then(data => data))
        createSongs(item).then(data => this.songs.push(data))
      })
    }

自定义prefixStyle根据浏览器添加样式前缀

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: {
//持续时间
duration: 400,
easing: linear   //线性动画
}
})
//将动画挂载到dom中
animations.runAnimation(this.$refs.cdWrapper,'move',done)  //第一个参数是dom,第二个是动画名,第三个是结束的回调

//在结束的回调记得将动画销毁
animations.unregisterAnimation(‘move')

使用三目运算符和computed属性改变icon的图标和动态改变keyframe动画

字符串补零的方法

// 其中num为你传的字符串,n为你要补到的位数
_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: {
//参数默认为调用事件的元素
  touchStart(e){
  let x = e.touchs[0].pageX    //e.touches[0],代表点击的第一个位置,pageX是第一个位置的x坐标
}
......
}
</scroll>

getBoundingClientRect()

getBoundingClientRect用于获取某个元素相对于视窗的位置集合。集合中有top, right, bottom, left等属性。


image.png
<!
返回值类型:
 rectObject.top:元素上边到视窗上边的距离;

rectObject.right:元素右边到视窗左边的距离;

rectObject.bottom:元素下边到视窗上边的距离;

rectObject.left:元素左边到视窗左边的距离;
!>
//一般是过去一个元素,然后去调用他对于视窗的距离,进行动态改变样式
rectObject = object.getBoundingClientRect();
rectObject.left   //这就获取到元素左边到视窗左边的距离

vue中的mixins属性

<meta charset="utf-8">

minxin其实是一个对象,里面的结构大致跟普通组件的script里面的一样,有data属性,钩子函数和方法等
混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

在实际项目中,可以新建一个js文件,导出一个minxin对象 在引用的组件中引入使用即可
这里例子就简单的跟官网一样帮助理解即可

选项合并

当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。

比如,数据对象在内部会进行浅合并 (一层属性深度),在和组件的数据发生冲突时以组件数据优先。

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" }
  }
})

同名钩子函数将混合为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。

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"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • vue去哪网跟学笔记 记录学习点滴 1. 初始化项目 1.1 手机显示配适 minimum-scale=1.0,m...
    noobakong阅读 2,295评论 0 16
  • Vue 课程学习笔记 基础部分 方法创建在 method 的大括号里面 可以将 v-on:click 简写为 @c...
    ThornFUN阅读 680评论 0 0
  • 01 今天,春节,又叫“年节”、“大年”,是中华民族的传统佳节,春节是新的开始...
    好时光生活荟阅读 488评论 0 1
  • 第一次来澳门,感觉到了一个童话城堡里。除了大三巴和妈祖庙好像没有特别的景点。但这里的每一处都很特别。街上到处铺满五...
    热爱运动的小雨儿阅读 473评论 0 0
  • 星姐作业让我们看我的少女时代,我大概搜一下,是一部台湾校园青春剧。演员除了特别出演的三位其他均不认识。又是台湾剧,...
    灰姑的书房阅读 284评论 0 1