(1) export 和 export default 的区别
- export ( import ) 可以有多个,export default ( 默认导出 ) 只能有一个
- export导出后引用需要加 { } ,export default则不需要
(2) vuex
state.js
功能:状态数据
const state={
singer:{}
}
export default state
mutation-types.js
功能:放置方法名,或者对mutations做封装
export const SET_SINGER = 'SET_SINGER'
mutations.js
功能:操作state数据
import * as types from './mutation-types'
const matutaions = {
[types.SET_SINGER] (state,singer){ // singer是传入的参数
state.singer=singer
}
}
export default matutaions
getters.js
功能:获取state里的数据,对state数据做映射
export const singer = state => state.singer
actions.js
功能:放异步操作
function findIndex(list, song) {
return list.findIndex((item) => {
return item.id === song.id
})
}
index.js
功能: 入口文件
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import state from './state'
import mutations from './mutations'
import createLogger from 'vuex/dist/logger' // 打印motation的修改纪录
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
// 调试工具,在dev环境开启,在production环境关闭
export default new Vuex.Store({
actions,
getters,
state,
mutations,
strict: debug,
plugins: debug ? [createLogger()] : []
})
存数据 ( 到 vuex 的 state 中 )
singer.vue
import {mapMutations} from 'vuex' // 语法糖
methods: {
selectSinger(singer) { // 子组件派发的this.$emit('select',item),这个item就是singer
this.$router.push({
path: `/singer/${singer.id}`
})
this.setSinger(singer)
// 在...mapMutations中取得setSinger方法,singer数据作为参数传给该方法,该方法改变state中的singer
},
_getSingerList() {
getSingerList().then((res) => {
if (res.code === ERR_OK) {
this.singers = this._normalizeSinger(res.data.list)
}
})
},
...mapMutations({
setSinger: 'SET_SINGER' // 映射成一个setSinger方法,对应的是mutation-types.js中的常量
})
},
取数据 ( 在 vuex 的 state 中 )
singer-detail.js
import {mapGetters} from 'vuex'
computed: {
...mapGetters([ // 扩展到computed中,是一个数组
'singer'
])
}
(3) router.beforeEach((to, from, next) => { })
导航钩子:作用是拦截导航
http://blog.csdn.net/wenyun_kang/article/details/70987840
https://segmentfault.com/a/1190000011140870
(详细)http://www.jianshu.com/p/2578cc444b70
(详细)http://www.jianshu.com/p/9798e3e63998
(1) 全局的钩子router.beforeEach((to, from, next) => { } )
(2) 路由元信息 meta 字段,标记是否需要检测导航
- 在router文件夹的index.js中
router/index.js
export default new Router({
routes: [
{
path: '/',
name: 'home',
redirect: '/recommend',
meta: { // 路由元信息字段,表示是否需要检测导航,true表示需要检测
needLogin: true
}
},
{
path: '/login',
component: Login
},
{
path: '/recommend',
name: 'recommend',
component: Recommend
},
{
path: '/singer',
name: 'singer',
component: Singer,
meta: {
needLogin: true
},
children: [{
path: ':id',
component: SingerDetail,
meta: {
needLogin: true
}
}]
}
]
})
- 在main.js中
main.js
router.beforeEach((to, from, next) => {
if (to.meta.needLogin) { // 如果目标页面需要登陆
if (window.sessionStorage.data) { // 但是同时已经登陆过了,有session
next() // 直接跳转到目标页面
} else {
alert('请先登录')
next('/login') // 否则跳转到登陆页面
}
} else {
next() // 如果不需要登陆,直接跳转到目标页面
}
})
- 在login.js中
login.js
methods: {
login() {
this.$http.post('https://www.easy-mock.com/mock/59d2fed09cabc90bb5e5c287/music/login', {
phone: `${this.userName}`,
password: `${this.passName}`
}).then((response) => {
console.log(response, 'response')
console.log(response.data, 'response.data')
if (response.data.data) { // 如果提交成功,返回数据存在
let ses = window.sessionStorage
let data = JSON.stringify(response.data.data)
ses.setItem('data', data) // 设置session,需要以字符串方式存储
this.$router.push('/') // 跳转路由
} else {
console.log('有错误')
}
})
}
}
(4) v-bind:style='' '' 绑定样式属性
- v-bind:style 它是一个 JavaScript 对象
http://blog.csdn.net/qiphon3650/article/details/73716220
(1)
// 一般绑定到样式属性上,计算属性
computed: {
bgStyle() {
return {
'background-image': `url(${this.bgImage})`,
border: '1px solid red'
}
// return `background-image:url(${this.bgImage})`
}
}
-----------------------------------------------------------------------
(2)
// 这种方式不提倡,不直观
data: {
activeColor: 'red',
fontSize: 30
}
(5) 在不同宽度的设备上,让图片宽度为设备宽度,且高度和宽度相等
- 注意:这种布局不要在class="bg-image"的div中直接写内容(比如文字,这样不会在div中),需要在里面再加子div,在子div中写内容,子div用绝对定位
.bg-image
position: relative
width: 100%
height: 0
padding-top: 100%
transform-origin: top
background-size: cover
.filter
position: absolute
top: 0
left: 0
width: 100%
height: 100%
background: rgba(7, 17, 27, 0.4)
(6) promise 封装axios请求
test2.js
import axios from 'axios'
// import Vue from 'vue'
// Vue.prototype.$http = axios
export function getSongs() {
return axios.get('/api/artist/album?id=6452&limit=30').then((response) => {
return Promise.resolve(response)
})
}
-----------------------------------------------------------------------
search.vue
import {getSongs} from 'api/test2.js'
export default {
created() {
this.getData()
},
methods: {
getData() {
getSongs().then((data) => {
console.log(data)
})
}
}
}
----------------------------------------------------------------
上面的/api是使用了代理,如下配置:
config/index.js
proxyTable:{
'/api': {
target: 'http://localhost:3000/',
changeOrigin: true,
pathRewrite: {
'^/api':''
}
}
}
访问 ('/api/artist/album?id=6452&limit=30')
其实是:http://localhost:3000/api/artist/album?id=6452&limit=30
(7)
this.$router.push() 跳转
this.$router.back() 返回
(1) this.$router.push
selectSinger(singer) { // 子组件派发的this.$emit('select',item),这个item就是singer
this.$router.push({
path: `/singer/${singer.id}`
})
this.setSinger(singer)
// 在...mapMutation中取得setSinger方法,singer数据作为参数传给state
},
--------------------------------------------
(2) this.$router.back()
methods: {
back() {
this.$router.back()
}
},
(8) watch 观察者
- watch方法响应数据的变化,当你想要在数据变化响应时,执行异步操作或开销较大的操作,这是很有用的。
- Vue.js 提供了一个方法 watch,它用于观察Vue实例上的数据变动。对应一个对象,键是观察表达式,值是对应回调。值也可以是方法名,或者是对象,包含选项。
https://q.cnblogs.com/q/91448/
http://blog.csdn.net/itkingone/article/details/69568498
http://blog.csdn.net/lemon_zhao/article/details/52191527
(官网)https://cn.vuejs.org/v2/api/#vm-watch
(知乎)https://www.zhihu.com/question/39155535?sort=created
例一:
例二: