一、vue的vue.config.js文件配置:(路径别名+反向代理)
//在项目根目录下建vue.config.js文件
//webpack配置(反向代理+路径别名配置)
const path = require('path')
module.exports = {
devServer : {//反向代理配置
proxy : {
'/ajax':{
target:'http://m.maoyan.com/',//目标源
changeOrigin:true,//运行修改源为http://localhost:8080
}
}
},
chainWebpack : config => {//路径别名配置
config.resolve.alias
.set('assets',path.join(__dirname,'./src/assets'))
.set('stylesheets',path.join(__dirname,'./src/assets/stylesheets'))
.set('components',path.join(__dirname,'./src/components'))
.set('lib',path.join(__dirname,'./src/lib'))
.set('utils',path.join(__dirname,'./src/utils'))
},
lintOnSave : true,//消除eslint的语法检测
}
二、rem.js做移动端适配
/*
通过js来动态添加rem,属于淘宝方案
*/
;(function(designWidth, maxWidth) {
var doc = document,
win = window,
docEl = doc.documentElement,
remStyle = document.createElement("style"),
tid;
function refreshRem() {
var width = docEl.getBoundingClientRect().width;
maxWidth = maxWidth || 540;
width>maxWidth && (width=maxWidth);
var rem = width * 100 / designWidth;
remStyle.innerHTML = 'html{font-size:' + rem + 'px;}';
}
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(remStyle);
} else {
var wrap = doc.createElement("div");
wrap.appendChild(remStyle);
doc.write(wrap.innerHTML);
wrap = null;
}
//要等 wiewport 设置好后才能执行 refreshRem,不然 refreshRem 会执行2次;
refreshRem();
win.addEventListener("resize", function() {
clearTimeout(tid); //防止执行两次
tid = setTimeout(refreshRem, 300);
}, false);
win.addEventListener("pageshow", function(e) {
if (e.persisted) { // 浏览器后退的时候重新计算
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}
}, false);
if (doc.readyState === "complete") {
doc.body.style.fontSize = "16px";
} else {
doc.addEventListener("DOMContentLoaded", function(e) {
doc.body.style.fontSize = "16px";
}, false);
}
})(375, 750);
三、重置样式reset.css
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td { margin:0; padding:0; }
body { background:#fff; color:#555; font-size:14px; font-family: "Arial","Microsoft YaHei","黑体","宋体",sans-serif; }
td,th,caption { font-size:14px; }
h1, h2, h3, h4, h5, h6 { font-weight:normal; font-size:100%; }
address, caption, cite, code, dfn, em, strong, th, var { font-style:normal; font-weight:normal;}
a { color:#fff; text-decoration:none; }
a:hover { text-decoration:none; color:white;}
img { border:none; }
ol,ul,li { list-style:none; }
input, textarea, select, button { font:14px "Arial","Microsoft YaHei","黑体","宋体",sans-serif; }
table { border-collapse:collapse; }
html {overflow-y: scroll;}
.clearfix:after {content: "."; display: block; height:0; clear:both; visibility: hidden;}
.clearfix { *zoom:1; }/*公共类*/
.fl { float:left}
.fr {float:right}
.al {text-align:left}
.ac {text-align:center}
.ar {text-align:right}
.hide {display:none}
html,body,#app{
height:100%;
}
四、移动端1px兼容(border.styl文件,在需要的vue组件的style样式部分以@import "~assets/stylesheets/border.styl"
,前面加了’~'才能正常解析,以border 0 0 1px 0 ,color 使用)
border($border-width = 1px, $border-color = #ccc, $border-style = solid, $radius = 0)
// 为边框位置提供定位参考
position: relative;
if $border-width == null
$border-width: 0;
border-radius: $radius;
&::after
// 用以解决边框layer遮盖内容
pointer-events: none;
position: absolute;
z-index: 999;
top: 0;
left: 0;
// fix当元素宽度出现小数时,边框可能显示不全的问题
// overflow: hidden;
content: "\0020";
border-color: $border-color;
border-style: $border-style;
border-width: $border-width;
// 适配dpr进行缩放
@media (max--moz-device-pixel-ratio: 1.49), (-webkit-max-device-pixel-ratio: 1.49), (max-device-pixel-ratio: 1.49), (max-resolution: 143dpi), (max-resolution: 1.49dppx)
width: 100%;
height: 100%;
if $radius != null {
border-radius: $radius;
}
@media (min--moz-device-pixel-ratio: 1.5) and (max--moz-device-pixel-ratio: 2.49), (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 2.49),(min-device-pixel-ratio: 1.5) and (max-device-pixel-ratio: 2.49),(min-resolution: 144dpi) and (max-resolution: 239dpi),(min-resolution: 1.5dppx) and (max-resolution: 2.49dppx)
width: 200%;
height: 200%;
transform: scale(.5)
if $radius != null {
border-radius: $radius * 2;
}
@media (min--moz-device-pixel-ratio: 2.5), (-webkit-min-device-pixel-ratio: 2.5),(min-device-pixel-ratio: 2.5), (min-resolution: 240dpi),(min-resolution: 2.5dppx)
width: 300%;
height: 300%;
transform: scale(.33333)
if $radius != null {
border-radius: $radius * 3;
}
transform-origin: 0 0;
五、超出部分呈现省略号,也是在样式处引入,@import "~assets/stylesheets/ellipsis.styl"
,以ellipsis()
使用即可
wrap($is-wrap = true)
if $is-wrap == true
word-wrap break-word
word-break break-all
else
white-space nowrap
ellipsis( $width = null, $line-clamp = 1 )
overflow hidden
text-overflow ellipsis
width $width
if abs( $line-clamp ) > 1
display -webkit-box !important
-webkit-line-clamp $line-clamp
flex-direction column
wrap()
else
wrap(false)
六、路由部分,因要全局使用,所以还要在main.js引入
import Vue from 'vue'
import VueRouter from 'vue-router'
// const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')//路由懒加载
const Film = () => import(/* webpackChunkName: "group-foo" */ '../pages/Film/Film.vue')
const Cinema = () => import(/* webpackChunkName: "group-foo" */ '../pages/Cinema/Cinema.vue')
const Mine = () => import(/* webpackChunkName: "group-foo" */ '../pages/Mine/Mine.vue')
const MovieNowHot = () => import(/* webpackChunkName: "group-foo" */ '../pages/Film/MovieNowHot.vue')
const MovieComingHot = () => import(/* webpackChunkName: "group-foo" */ '../pages/Film/MovieComingHot.vue')
const Error = () => import(/* webpackChunkName: "group-foo" */ '../pages/Error/Error.vue')
Vue.use(VueRouter)
const routes = [//配置路由表
{
path:'/',
redirect:'/film/n.hot'
},
{
path:'/film',
component:Film,
children:[
{
path:'n.hot',
component:MovieNowHot
},
{
path:'f.hot',
component:MovieComingHot
}
]
},
{
path:'/cinema',
component:Cinema
},
{
path:'/mine',
component:Mine
},
{
path:'/error',
component:Error
},
{
path:'*',
redirect:'/error'
}
]
const router = new VueRouter(
{
routes,
mode:'history',
}
)
export default router
七、猫眼移动端的 main.js 文件
import Vue from 'vue'
import App from './App.vue'
//全局引入路由
import router from './router/index.js'
//引入rem.js进行布局
import 'utils/rem.js'
//引入reset.css进行样式重置
import 'stylesheets/reset.css'
import store from './store'
//引入过滤器
import './utils/filter'
//引入提示Toast的样式文件
import { Indicator } from 'mint-ui';
import 'mint-ui/lib/style.css'
//添加axios拦截器(添加loading效果)
import axios from 'axios'
axios.interceptors.request.use(function (config) {
// Do something before request is sent
Indicator.open({
text: 'Loading...',
spinnerType: 'fading-circle'
});
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// Do something with response data
Indicator.close();
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
Vue.config.productionTip = false
new Vue({
store,
router,
render: h => h(App),
}).$mount('#app')
八、vuex做状态管理
//store/index.js文件
import Vuex from 'vuex'
import Vue from 'vue'
import movieStore from './movie/index.js'
Vue.use( Vuex )
const store = new Vuex.Store({
modules:{
movieStore,
}
})
export default store
// movie/index.js文件
import state from './state'
import actions from './actions'
import mutations from './mutations'
import getters from './getters'
const movieStore = {
state,
actions,
mutations,
getters
}
export default movieStore
// state.js
const state = {
n_hot_movies:null,
more_movies:null,
f_hot_movies:null,
}
export default state
// actions.js
import * as type from './type'
import axios from 'axios'
const actions = {
getNowHotMovies ({commit}) {
axios({
url:'/ajax/movieOnInfoList',
method:'get',
params:{
token:''
}
}).then(res=>{
// console.log('movie-data',res)
const action = {
type:type.GET_NOW_HOT_MOVIE,
payload:res
}
commit(action)
})
.catch(error=>console.log('error',error))
},
getMoreComingMovies ({commit},ids) {
axios({
url:'/ajax/moreComingList',
method:'get',
params:{
token:'',
movieIds:ids
}
}).then(res=>{
// console.log('more-movie-data',res)
const action = {
type:type.GET_MORE_COMING_MOVIE,
payload:res
}
commit(action)
})
.catch(error=>console.log('error',error))
},
getFutureHotMovies ({commit}) {
axios({
url:'/ajax/mostExpected',
method:'get',
params:{
ci: 50,
limit: 10,
offset: 0,
token: ''
}
}).then(res=>{
// console.log('GET_FUTURE_HOT_MOVIE',res)
const action = {
type:type.GET_FUTURE_HOT_MOVIE,
payload:res
}
commit(action)
})
.catch(error=>console.log('error',error))
},
}
export default actions
// mutations.js
import * as type from './type'
const mutations = {
[type.GET_NOW_HOT_MOVIE] (state,action) {
state.n_hot_movies = action.payload
},
[type.GET_MORE_COMING_MOVIE](state,action){
state.more_movies = action.payload
},
[type.GET_FUTURE_HOT_MOVIE](state,action){
state.f_hot_movies = action.payload
}
}
export default mutations
// type.js
export const GET_NOW_HOT_MOVIE = 'GET_NOW_HOT_MOVIE'
export const GET_MORE_COMING_MOVIE = 'GET_MORE_COMING_MOVIE'
export const GET_FUTURE_HOT_MOVIE = "GET_FUTURE_HOT_MOVIE"
// getters.js
const getters = {
new_n_hot_movies (state) {
return state.n_hot_movies
},
new_more_movies(state){
return state.more_movies
},
new_f_hot_movies(state){
return state.f_hot_movies
}
}
export default getters
//这里`import { mapActions, mapGetters } from 'vuex';`其实是将actions和getters里面的方法绑定在组件的this上了
methods: {
...mapActions(['getFutureHotMovies'])
},
computed: {
...mapGetters(['new_f_hot_movies']),
},
九、filter过滤器
import Vue from 'vue'
Vue.filter('imgFilter',(value,size)=>{
return value.replace('w.h',size)
})
//最后可以在mian.js里引入,全局使用
// 使用时比如:`<img :src="item.img|imgFilter(`85.115`)" alt="">`做图片宽高过滤处理