移动端rem适配
Vant 中的样式默认使用 px
作为单位,如果需要使用 rem
单位,推荐使用以下两个工具:
- postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 rem
- lib-flexible 用于设置 rem 基准值
一、使用 lib-flexible 动态设置 REM 基准值(html 标签的字体大小)
1、安装
# yarn add amfe-flexible
npm i amfe-flexible
2、然后在 main.js
中加载执行该模块
import 'amfe-flexible'
3.查看浏览器调试工具中的观察 html 标签 font-size
的变化
二、使用 postcss-pxtorem 将 px
转为 rem
1、安装
# yarn add -D postcss-pxtorem
# -D 是 --save-dev 的简写
npm install postcss-pxtorem -D
2、然后在项目根目录中创建 .postcssrc.js
文件
module.exports = {
plugins: {
'autoprefixer': {
browsers: ['Android >= 4.0', 'iOS >= 8']
},
'postcss-pxtorem': {
rootValue: 37.5,
propList: ['*']
}
}
}
3、配置完毕,重新启动服务
4、查看浏览器调试工具审查元素的样式查看是否已将 px
转换为 rem
需要注意的是:
- 该插件不能转换行内样式中的
px
,例如<div style="width: 200px;"></div>
Postcss文件解释
/**
* PostCSS 配置文件
*/
module.exports = {
// 配置要使用的 PostCSS 插件
plugins: {
// 配置使用 autoprefixer 插件
// 作用:生成浏览器 CSS 样式规则前缀
// VueCLI 内部已经配置了 autoprefixer 插件
// 所以又配置了一次,所以产生冲突了
// 'autoprefixer': { // autoprefixer 插件的配置
// // 配置要兼容到的环境信息
// browsers: ['Android >= 4.0', 'iOS >= 8']
// },
// 配置使用 postcss-pxtorem 插件
// 作用:把 px 转为 rem
'postcss-pxtorem': {
// lib-flexible 的 REM 适配方案:把一行分为 10 份,每份就是十分之一
// 所以 rootValue 应该设置为你的设计稿宽度的十分之一
// 我们的设计稿是 750,所以应该设置为 750 / 10 = 75
// 但是 Vant 建议设置为 37.5,为什么?因为 Vant 是基于 375 写的
// 所以必须设置为 37.5,唯一的缺点就是使用我们设计稿的尺寸都必须 / 2
// 有没有更好的办法?
// 如果是 Vant 的样式,就按照 37.5 来转换
// 如果是 我们自己 的样式,就按照 75 来转换
// 通过查阅文档,我们发现 rootValue 支持两种类型:
// 数字:固定的数值
// 函数:可以动态处理返回
// postcss-pxtorem 处理每个 CSS 文件的时候都会来调用这个函数
// 它会把被处理的 CSS 文件相关的信息通过参数传递给该函数
rootValue({ file }) {
return file.indexOf('vant') !== -1 ? 37.5 : 75;
},
// rootValue: 75,
// 配置要转换的 CSS 属性
// * 表示所有
propList: ['*'],
// 配置不要转换的样式资源
exclude: 'github-markdown'
}
}
};
加载第三方图片资源403问题解决
这是因为我们项目的接口数据是后端通过爬虫抓取的第三方平台内容,而第三方平台对图片资源做了防盗链保护处理。
第三方平台怎么处理图片资源保护的?
服务端一般使用 Referer 请求头识别访问来源,然后处理资源访问。
解决: 1. 直接在 HTMl 页面头中通过 meta 属性全局配置
<meta name="referrer" content="no-referrer" />
- 用
<a>
、<area>
、<img>
、<iframe>
、<script>
或者<link>
元素上的referrerpolicy
属性为其设置独立的请求策略
<img src="http://……" referrerPolicy="no-referrer">
处理时间的dayjs插件
Day.js 是一个轻量的处理时间和日期的 JavaScript 库,和 Moment.js 的 API 设计保持完全一样,如果您曾经用过 Moment.js, 那么您已经知道如何使用 Day.js 。
- Day.js 可以运行在浏览器和 Node.js 中。
- 🕒 和 Moment.js 相同的 API 和用法
- 💪 不可变数据 (Immutable)
- 🔥 支持链式操作 (Chainable)
- 🌐 国际化 I18n
- 📦 仅 2kb 大小的微型库
- 👫 全浏览器兼容
- 安装
cnpm i dayjs
- 使用
import dayjs from 'dayjs'
import 'dayjs/locale/zh-cn'
dayjs.locale('zh-cn')
console.log(dayjs().format('YYYY-MM-DD'))
- 在
main.js
中加载初始化
import './utils/dayjs'
- 定义处理时间的过滤器
import Vue from 'vue'
import dayjs from 'dayjs'
// 加载中文语言包
import 'dayjs/locale/zh-cn'
import relativeTime from 'dayjs/plugin/relativeTime'
// 配置使用处理相对时间的插件
dayjs.extend(relativeTime)
// 配置使用中文语言包
dayjs.locale('zh-cn')
// 全局过滤器:处理相对时间
Vue.filter('relativeTime', value => {
return dayjs().to(dayjs(value))
})
lodash库中debounce防抖处理
_.debounce(func, [wait=0], [options=])
func:要防抖的函数
wait=0:需要延迟的毫秒数
searchText: {
// lodash中的debounce防抖处理
handler: debounce(function (val) {
this.localSearchSuggestions(val)
}, 300),
// handler (val) {
// this.localSearchSuggestions(val)
// },
immediate: true
}
axios/解决后端数据大数字的问题
json-bigint
GitHub网址:https://github.com/sidorares/json-bigint
当我们在写项目的时候调用后台接口的地址需要接收一个id值例如:(id:9223372036854776000)
JavaScript 能够准确表示的整数范围在-253到253之间(不含两个端点),超过这个范围,无法精确表示这个值,这使得 JavaScript 不适合进行科学和金融方面的精确计算
浏览器会默认解析得到数值与原数值不匹配导致404问题
解决这个问题我们使用第三方插件JSON-BigInt
1. 安装
npm i json-bigint
2. 导入
var JSONbig = require('json-bigint')
3. 使用
JSONbig.parse()
将json格式字符串转化为对象与JSON.parse()类似
var json = '{ "value" : 9223372036854775807}'
// 将json字符串转为对象
console.log(JSON.parse(json))// 9223372036854776000
console.log(JSONbig.parse(json).value.toString())// 是一个对象 需要toSring() 9223372036854776000
1234
JSONbig.stringify()
将对象转化为json格式字符串与JSON.stringify()类似
// 将对象还原为json格式的字符串
console.log(JSON.stringify(JSONbig.parse(json))) // {"value":"9223372036854775807"}改变了原数据的值的数据类型
console.log(JSONbig.stringify(JSONbig.parse(json)))// {"value":9223372036854775807} 没有改变原数据
123
通过 Axios 请求得到的数据都是 Axios 处理(JSON.parse)之后的,我们应该在 Axios 执行处理之前手动使用 json-bigint 来解析处理。Axios 提供了自定义处理原始后端返回数据的 API:transformResponse
。
import axios from 'axios'
var jsonBig = require('json-bigint')
const request = axios.create({
baseURL: 'http://ttapi.research.itcast.cn/', // 接口基础路径
// transformResponse 允许自定义原始的响应数据(字符串)
transformResponse: [function (data) {
try {
// 如果转换成功则返回转换的数据结果
return jsonBig.parse(data)
} catch (err) {
// 如果转换失败,则包装为统一数据格式并返回
return {
data
}
}
}]
})
export default request
//“transformRequest”允许在将请求数据发送到服务器之前对其进行更改
//这只适用于请求方法“PUT”、“POST”、“PATCH”和“DELETE”
//数组中的最后一个函数必须返回字符串或Buffer的实例ArrayBuffer,
//FormData或流
//您可以修改headers对象
// `transformRequest` allows changes to the request data before it is sent to the server // This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE' // The last function in the array must return a string or an instance of Buffer, ArrayBuffer, // FormData or Stream // You may modify the headers object transformRequest: [function (data, headers) { // Do whatever you want to transform the data return data; }],
vue-父子组件中的传值(数组,对象)
<!--父组件 -->
<template>
<div class='container' v-for='(item,i) in list' :key='i'>{{item}}</div>
<SonList :lists='list'></SonList>
</template>
<script>
import SonList from '组件名'
export default {
name: '',
data () {
return {
list:[1,2,3,4,5]
}
},
created () {},
methods: {},
computed: {}
}
</script>
<style lang='less' scoped>
</style>
<!--子组件-->
<!-- 点击按钮添加数据-->
<template>
<button @click='addData'>
点击
</button>
</template>
<script>
export default {
name: '',
props:{
lists:{
type:Array,
required:true
}
},
data () {
return {
}
},
created () {},
methods: {
addData(){
this.lists.push(this.lists.length++)
}
},
computed: {}
}
</script>
<style lang='less' scoped>
</style>
vue中子组件要修改父组件中的值,他不会监听到数组或对象的变化,因为在数组或对象是存储到堆中修改数据并没有改变堆中地址的变化,所以不会报错
vue-路由组件传参
- $route
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
在组件中使用
$route
会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。
- props解耦
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, props: true },
// 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
})
vue-依赖注入
在写项目的时候,多个子组件用到了父组件的一个或多个值,可以使用vue中依赖注入方便使用,不需要一级一级的传值,比如:层级比较深的情况
provide
选项允许我们指定我们想要提供给后代组件的数据/方法。
provide
选项应该是一个对象或返回一个对象的函数。
provide: function () {
return {
getMap: this.getMap //要共享出去的数据
}
}
在任何后代组件里,我们都可以使用 inject
选项来接收指定的我们想要添加在这个实例上的 property:
- inject 选项应该是:
- 一个字符串数组,或一个对象,对象的 key 是本地的绑定名,value 是:
在可用的注入内容中搜索用的 key (字符串或 Symbol),或一个对象,该对象的:
from property 是在可用的注入内容中搜索用的 key (字符串或 Symbol)
default property 是降级情况下使用的 value
- 一个字符串数组,或一个对象,对象的 key 是本地的绑定名,value 是:
inject: ['getMap']
注意:不要滥用
vue-自定义组件v-model与.sync
修饰符
.sync修饰符
有时我们需要父组件向子组件传值,并且子组件要修改父组件中的值是,我们一般会这样写
//父组件
<template>
//子组件修改值 父组件注册自定义事件 传过来的参数通过$event来获取
<div :title='title' @update-title=’title=$event‘>
{{title}}
</div>
</template>
<script>
export default {
data () {
return {
title:’父组件的值‘
}
}
}
</script>
<style lang='less' scoped>
</style>
//子组件
<template>
<button @click=’$emit('update-title','子组件修改的值')‘>
// 如果我们要修改父组件中的值 1.发送一个通知给父组件 2.父组件接到通知去修改自己的值
//我们需要把父组件的title放到组件中使用
{{title}}
</button>
</template>
<script>
export default {
props:['title']
data () {
return {
}
}
}
</script>
<style lang='less' scoped>
</style>
由于父向子传值 子组件也要修改父组件的值vue提供了一个修饰符可以更好的简化代码(.sync)
//父组件
<template>
//子组件修改值 父组件注册自定义事件 传过来的参数通过$event来获取
<div :title.sync='title'>
{{title}}
</div>
</template>
<script>
export default {
data () {
return {
title:’父组件的值‘
}
}
}
</script>
<style lang='less' scoped>
</style>
//子组件
<template>
<button @click=’$emit('update:title','子组件修改的值')‘>
//我们需要把父组件的title放到组件中使用
{{title}}
</button>
</template>
<script>
export default {
props:['title']
data () {
return {
}
}
}
</script>
<style lang='less' scoped>
</style>
注意带有
.sync
修饰符的v-bind
不能和表达式一起使用 (例如v-bind:title.sync=”doc.title + ‘!’”
是无效的)。取而代之的是,你只能提供你想要绑定的 property 名,类似v-model
$emit('update:要传入的值')
是固定写法
自定义组件的v-model
之前我们使用v-model
指令用来做数据的双向绑定
由于父向子传值 子组件也要修改父组件的值vue除了
.sync
修饰符可以更好的简化代码,另一个就是自定义组件v-model
自定义组件v-model提供了默认的props,通过value来绑定数据源,通过监听input事件来向父组件传值
//父组件
<template>
//子组件修改值 父组件注册自定义事件 传过来的参数通过$event来获取
<div :value='title' @input=’title=$event‘>
{{title}}
</div>
</template>
<script>
export default {
data () {
return {
title:’父组件的值‘
}
}
}
</script>
<style lang='less' scoped>
</style>
//子组件
<template>
<button @click=’$emit('input','子组件修改的值')‘>
// 如果我们要修改父组件中的值 1.发送一个通知给父组件 2.父组件接到通知去修改自己的值
//我们需要把父组件的title放到组件中使用
{{title}}
</button>
</template>
<script>
export default {
props:['title']
data () {
return {
}
}
}
</script>
<style lang='less' scoped>
</style>
其实value 和input是默认情况,当我们可以修改名称,通过model属性来修改
model: { prop: ‘checked’, event: ‘change’ }
//父组件
<template>
//子组件修改值 父组件注册自定义事件 传过来的参数通过$event来获取
<div :title='title' @update-title=’title=$event‘>
{{title}}
</div>
</template>
<script>
export default {
data () {
return {
title:’父组件的值‘
}
}
}
</script>
<style lang='less' scoped>
</style>
//子组件
<template>
<button @click=’$emit('update-title','子组件修改的值')‘>
// 如果我们要修改父组件中的值 1.发送一个通知给父组件 2.父组件接到通知去修改自己的值
//我们需要把父组件的title放到组件中使用
{{title}}
</button>
</template>
<script>
export default {
//修改名称
model: {
prop: 'title',
event: 'update-title'
},
props:['title']
data () {
return {
}
}
}
</script>
<style lang='less' scoped>
</style>
注意
自定义组件的v-model
与.sync
不同的区别是
v-model
一个组件只能绑定一次.sync
可以绑定多个