版本:
- node 14
- @vue/cli 4.0.5
- package.json配置 “@vue/cli-service”: “^4.1.0”,
html-loader - 解决模板字符串
下载 : npm install —save-dev html-loader
版本 : “html-loader”: “^0.5.5”,
解决在写视口标签时使用模板字符串和变量html-plugin无法处理的问题
//window.devicePixelRatio告诉浏览器应使用多少屏幕实际像素来绘制单个CSS像素 返回1|2|3|?let scale = 1.0 / window.devicePixelRatio;//设置视口标签let text = `<meta name="viewport" content="width=device-width, initial-scale=${scale}, maximum-scale=${scale}, minimum-scale=${scale}, user-scalable=no">`;document.write(text);
由于是vue-cli创建的没有webpack.config,所以新建一个vue.config配置html-loader
module.exports = {configureWebpack: {//自定义webpack配置module: {rules: [{test: /\.(html)$/,exclude: /node_modules/,use: {loader: 'html-loader',options: {minimize: true}}}]}},}
postcss-pxtorem - 实现自动将px转换成rem
下载 : npm i -D postcss-pxtorem
版本 : “html-loader”: “^0.5.5”,
同时新增配置: postcss.config.js
module.exports = {plugins: {autoprefixer: {},'postcss-pxtorem': {rootValue: 100, // 根元素字体大小// propList: ['width', 'height'], //只对这两个属性转换rem,因为有很多标签 所以还是用 *//,如果指向排斥某一标签 则将px改为Px(variable.scss)propList: ['*']}}}
webpack - 实现CSS3/ES678语法的兼容
.browserslistrc 文件
ie >= 8Firefox >= 3.5chrome >= 35opera >= 11.5
fastclick - 解决移动端100~300ms的点击事件延迟问题
下载: npm install fastclick
版本: @1.0.6
main.js
import fastclick from 'fastclick'//解决移动端点击延迟fastclick.attach(document.body)
scss - 初始化默认的全局样式
1).base.scss - 全局标签属性配置(html, body) 该文件引入234 main.js引入该组件<br /> 2).mixin.scss - 各种函数(bg_color修改背景颜色)<br /> 3).variable.scss - 定义字体大小&颜色($font_samll:12Px;)<br /> 4).rest.scss - 初始化标签样式(ol,ul{list-style:none})
注意点: 在移动端开发中, 一般情况下我们不需要让字体大小随着屏幕尺寸的变化而变化(mixin.scss - font_dpr())
由于我们是通过视口缩放来适配移动端的, 所以我们不能直接设置字体大小, 否则字体大小就会随着屏幕尺寸的变化而变化
base.scss
@import "./reset.scss";
@import "./variable.scss";
@import "./mixin.scss";
html, body{
width: 100%;
height: 100%;
overflow: hidden;
// 解决IScroll拖拽卡顿问题
touch-action: none;
}
body{
@include font_size($font_medium);
font-family: Helvetica,sans-serif,STHeiTi;
}
img{
vertical-align: bottom;
}
mixin.scss
@import "./variable.scss";
/*根据dpr计算font-size*/
@mixin font_dpr($font-size){
font-size: $font-size;
// 根据像素比缩放字体大小 达到视口变化而字体不变
[data-dpr="2"] & { font-size: $font-size * 2;}
[data-dpr="3"] & { font-size: $font-size * 3;}
}
/*通过该函数设置字体大小,后期方便统一管理;*/
@mixin font_size($size){
@include font_dpr($size);
}
// 不换行
@mixin no-wrap(){
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
// 限制行数
@mixin clamp($row){
overflow:hidden;
text-overflow:ellipsis;
display:-webkit-box;
-webkit-box-orient:vertical;
-webkit-line-clamp:$row;
}
//根据属性选择器设置背景颜色
@mixin bg_color(){
background: $background-color-theme;
[data-theme=theme1] & {
background: $background-color-theme1;
}
[data-theme=theme2] & {
background: $background-color-theme2;
}
}
//不同主题和不同像素比下显示不同图片
//不同设置background:url() 这样background-size不起作用
@mixin bg_img($url) {
[data-theme=theme] & {
background-image: url($url + '_163.png');
}
[data-theme=theme1] & {
background-image: url($url + '_qq.png');
}
[data-theme=theme2] & {
background-image: url($url + '_it666.png');
}
background-size: cover;
background-repeat: no-repeat;
[data-theme=theme][data-dpr='2'] & {
background-image: url($url + '_163@2x.png');
}
[data-theme=theme][data-dpr='3'] & {
background-image: url($url + '_163@3x.png');
}
[data-theme=theme1][data-dpr='2'] & {
background-image: url($url + '_qq@2x.png');
}
[data-theme=theme1][data-dpr='3'] & {
background-image: url($url + '_qq@3x.png');
}
[data-theme=theme2][data-dpr='2'] & {
background-image: url($url + '_it666@2x.png');
}
[data-theme=theme2][data-dpr='3'] & {
background-image: url($url + '_it666@3x.png');
}
}
//改变tabbar背景颜色
@mixin bg_sub_color(){
background: $background-color-sub-theme;
[data-theme=theme1] & {
background: $background-color-sub-theme1;
}
[data-theme=theme2] & {
background: $background-color-sub-theme2;
}
}
//改变tabbar字体颜色
@mixin font_color(){
color: $font-color-theme;
[data-theme=theme1] & {
color: $font-color-theme1;
}
[data-theme=theme2] & {
color: $font-color-theme2;
}
}
//改变tabbar字体激活线颜色
@mixin font_active_color(){
color: $font-active-color-theme;
[data-theme=theme1] & {
color: $font-active-color-theme1;
}
[data-theme=theme2] & {
color: $font-active-color-theme2;
}
}
//tabbar下划线
@mixin border_color(){
border-color: $border-color-theme;
[data-theme=theme1] & {
border-color: $border-color-theme1;
}
[data-theme=theme2] & {
border-color: $border-color-theme2;
}
}
variable.scss
//字体定义规范
$font_samll:12Px;
$font_medium_s:13Px;
$font_medium:15Px;
$font_large:17Px;
// 背景颜色规范(主要)
$background-color-theme: #d43c33;//背景主题颜色默认(网易红)
$background-color-theme1: rgba(34,213,156,1);//背景主题颜色1(QQ绿)
$background-color-theme2: #333;//背景主题颜色2(夜间模式)
// 背景颜色规范(次要)
$background-color-sub-theme: #f5f5f5;//背景主题颜色默认(网易红)
$background-color-sub-theme1: #f5f5f5;//背景主题颜色1(QQ绿)
$background-color-sub-theme2: #444;//背景主题颜色2(夜间模式)
// 字体颜色规范(默认)
$font-color-theme : #666;//字体主题颜色默认(网易)
$font-color-theme1 : #666;//字体主题颜色1(QQ)
$font-color-theme2 : #ddd;//字体主题颜色2(夜间模式)
// 字体颜色规范(激活)
$font-active-color-theme : #d43c33;//字体主题颜色默认(网易红)
$font-active-color-theme1 : rgba(34,213,156,1);//字体主题颜色1(QQ绿)
$font-active-color-theme2 : #ffcc33;//字体主题颜色2(夜间模式)
// 边框颜色
$border-color-theme : #d43c33;//边框主题颜色默认(网易)
$border-color-theme1 : rgba(34,213,156,1);//边框主题颜色1(QQ)
$border-color-theme2 : #ffcc33;//边框主题颜色2(夜间模式)
rest.scss
/*
YUI 3.18.1 (build f7e7bcb)
Copyright 2014 Yahoo! Inc. All rights reserved.
Licensed under the BSD License.
http://yuilibrary.com/license/
*/
html{color:#000;background:#FFF}
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}
table{border-collapse:collapse;border-spacing:0}
fieldset,img{border:0}
address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}
ol,ul{list-style:none}
caption,th{text-align:left}
h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}
q:before,q:after{content:''}
abbr,acronym{border:0;font-variant:normal}
sup{vertical-align:text-top}
sub{vertical-align:text-bottom}
input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;*font-size:100%}
legend{color:#000}
a{text-decoration: none}
#yui3-css-stamp.cssreset{display:none}
axios
下载: npm install axios
版本: @0.19.0
network.js - 全局配置和调用方法定义
路径 : src/api/network.js
import axios from 'axios'
import Vue from 'vue'
// 进行一些全局配置
axios.defaults.baseURL = 'http://192.168.0.105:3000/'
axios.defaults.timeout = 5000
let count = 0 //记录请求次数
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
count++
Vue.showLoading()
return config
}, function (error) {
// 对请求错误做些什么
Vue.hiddenLoading()
return Promise.reject(error)
})
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
count--
if (count === 0) {
Vue.hiddenLoading()
}
return response
}, function (error) {
// 对响应错误做点什么
Vue.hiddenLoading()
return Promise.reject(error)
})
// 封装自己的get/post方法
export default {
get: function (path = '', data = {}) {
return new Promise(function (resolve, reject) {
axios.get(path, {
params: data
})
.then(function (response) {
resolve(response.data)
})
.catch(function (error) {
reject(error)
})
})
},
post: function (path = '', data = {}) {
return new Promise(function (resolve, reject) {
axios.post(path, data)
.then(function (response) {
resolve(response.data)
})
.catch(function (error) {
reject(error)
})
})
},
all: function (list) {
return new Promise(function (resolve, reject) {
axios.all(list)
.then(axios.spread(function (...result) {
// 两个请求现在都执行完成
resolve(result)
}))
.catch(function (err) {
reject(err)
})
})
}
}
index.js - 封装接口
路径 : src/api/index.js
// 这个JS文件就是专门用于管理请求各种接口地址的
import Network from './network'
// 封装各种接口请求
export const getBanner = () => Network.get('banner?type=2'); //获取 banner( 轮播图 ) 数据
//获取歌手分类(欧美/华语...)
//letter A-Z
export const getLetterArtists = (letter) => {
return new Promise(function (resolve, reject) {
let letterArtists = []
Network.all([
Network.get(`artist/list?type=-1&limit=5&area=7&initial=${letter}`),
Network.get(`artist/list?type=-1&limit=5&area=96&initial=${letter}`),
])
.then(function (result) {
//console.log(result)
result.forEach(function (item) {
letterArtists.push(...item.artists)
})
//console.log(letterArtists)
resolve([...new Set(letterArtists)])
})
.catch(function (err) {
reject(err)
})
})
}
调用
import {getBanner} from '../api/index'
created(){
getBanner({ id:XX})
.then((data) => {
console.log(data)
})
.catch((err) => {
console.log(err)
})
}
vue-awesome-swiper - 轮播图
下载: npm install swiper vue-awesome-swiper —save
版本: @3.1.3
注意:
- 最新版本配置不同 - 按照官网
- v-if=”banners.length > 0”自动轮播到最后一页之后继续轮播
- 如果想覆盖swiper的样式, 那么style标签不能是scoped的, 否则无法覆盖 ```vue
<a name="sTAgB"></a>
# vue-lazyload - 图片懒加载
下载: npm i vue-lazyload -S<br />版本: @1.3.3
<a name="sCYQZ"></a>
## main.js
```javascript
import VueLazyload from 'vue-lazyload'
import Loading from './plugin/loading/index'
Vue.use(Loading,{
title:'正在加载...'
})
Vue.use(VueLazyload, {
// 可以通过配置loading来设置图片还未加载好之前的占位图片
loading: require('./assets/images/loading.png')
})
component
<img v-lazy="value.picUrl">
ScrollView - 拖拽功能组件(废弃)
下载: npm install iscroll
版本: @5.2.0
ScrollView.vue 配置 插槽slot / 方法
<template>
<div id="wrapper" ref="wrapper">
<slot></slot>
</div>
</template>
<script>
import IScroll from 'iscroll/build/iscroll-probe'
export default {
name: 'ScrollView',
mounted () {
this.iscroll = new IScroll(this.$refs.wrapper, {
mouseWheel: true,
scrollbars: false,//是否显示滚动条
probeType:3,//像素级XX 可以获取拖动距离像素
// 解决拖拽卡顿问题
scrollX: false,
scrollY: true,
// disablePointer: true,
disableTouch: false,
disableMouse: true
});
//MutationObserver元素JS,节点变化时(axios拿到数据)刷新iscroll
// 1.创建一个观察者对象
/*
MutationObserver构造函数只要监听到了指定内容发生了变化, 就会执行传入的回调函数
mutationList: 发生变化的数组
observer: 观察者对象
* */
let observer = new MutationObserver((mutationList, observer) => {
this.iscroll.refresh()
})
// 2.告诉观察者对象我们需要观察什么内容
let config = {
childList: true, // 观察目标子节点的变化,添加或者删除
subtree: true, // 默认为 false,设置为 true 可以观察后代节点
attributeFilter: ['height', 'offsetHeight'] // 观察特定属性
}
// 3.告诉观察者对象, 我们需要观察谁, 需要观察什么内容
/*
config配置中变化则会触发observer函数
第一个参数: 告诉观察者对象我们需要观察谁
第二个参数: 告诉观察者对象我们需要观察什么内容
* */
observer.observe(this.$refs.wrapper, config)
},
methods:{
//提供一个监听滚动距离的方法给外界
scrolling (fn) {
this.iscroll.on('scroll', function () {
fn(this.y)
})
},
//提供一个组件刷新方法
refresh () {
setTimeout(() => {
this.iscroll.refresh()
}, 100)
},
//提供一个组件滚动方法
scrollTo (x, y, time) {
this.iscroll.scrollTo(x, y, time)
}
}
}
</script>
<style lang="scss" scoped>
#wrapper{
width: 100%;
height: 100%;
}
</style>
component
<template>
<div class="recommend">
<ScrollView>
<div>
//放组件
</div>
</ScrollView>
</div>
</template>
<script>
import ScrollView from '../components/ScrollView.vue'
export default {
name:"Recommend",
components:{
ScrollView
}
}
</script>
