小知识点
01 | 路径中@使用问题#
@ 在 scr 文件夹对应的是 src 文件夹
- 在 JS 中使用:
@/views/home/index.vue。代表是.../src/views/home/index.vue - 在 CSS 中如果想使用@来表示路径,需要在前面加上
~~@/views/home/index.vue。代表是.../src/views/home/index.vue
02 | CSS 深度操作符、深度选择器#
子组件样式 ,在 scoped 作用域中,只影响根节点,要影响后代节点,需要添加深度操作符 /deep/
当 <style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素
操作符有:
/deep/>>>:有些工具不认::v-deep
bug效果

解决办法:
// 方式一.home-container { ::v-deep.van-nav-bar__title { max-width: unset; }}// 方式二.home-container { /deep/.van-nav-bar__title { max-width: unset; }}03 | 数组展开操作... - 在合并数组的时候经常使用#
let list = [1,2,3,4,5]let list1 = [6,7,8,9]
// 如果想把list1添加到 list 中有以下办法// 1. 循环 list1,挨个添加到list -- 不推荐
// 2. 利用展开操作符`...`,添加list1到 list 中list.push(...list1)...arr:
会把数组中一个一个元素展开来
04 | 快速找到是哪个元素产生的滚动#
把下面的代码粘贴到调试工具中运行一下,然后滚动页面,就可以看到是哪个元素产生的滚动了
function findScroller(element) { element.onscroll = function() { console.log(element) } Array.from(element.children).forEach(findScroller)}
findScroller(document.body)如果多嵌套列表,如何让各自的文章列表有自己的滚动容器?
- 固定高度:
height:xxx; - 溢出滚动:
overflow-y:auto;
给列表的根节点设置样式如下:
.list { height: 100%; overflow-y: auto;}这时候可能会发现页面没了,是因为高度可能会 0,为 0 的原因是父元素没有高度。
解决办法就是用 vw 和 vh。
vw 和 vh 是 CSS3 增加的一种视口单位。视口:根据浏览器窗口的大小,不受父元素的影响
在移动端,视口单位相对于布局视口
- 1vh = 可视窗口高度的百分之一。比如窗口高度 750,则 1vh = 750 / 100 = 7.5px
- 1vw = 可视窗口宽度的百分之一。比如窗口高度 410,则 1w = 410 / 100 = 4.1px
使用它唯一需要注意的就是它的兼容性:
- pc 端已兼容到 IE9
- 在移动端 iOS 8 以上及 Android 4.4 以上获得支持,并且在微信 x5 内核也完美支持
最终给列表设置的样式如下:
.list { height: 79vh; overflow-y: auto;}05 | label 标签对 input 元素标注的使用方#
定义:
<label> 标签为 input 元素定义标注(标记)。
label 元素不会向用户呈现任何特殊效果。不过,它为鼠标用户改进了可用性。如果您在 label 元素内点击文本,就会触发此控件。就是说,当用户选择该标签时,浏览器就会自动将焦点转到和标签相关的表单控件上。
用法:
<label> 标签的 for 属性应当与相关元素的 id 属性相同。
开发为了增强用户体验,涉及 input 元素中的 checkbox、radio等属性时,常用 label 标签来标注,使之点击到文字也能选中相应的单选、复选框等。
常规 input 使用:
<input type="radio" name="demo" />单选1<input type="radio" name="demo" />单选2<input type="radio" name="demo" />单选3<input type="radio" name="demo" />单选4<input type="radio" name="demo" />单选5这时候只有点击相应的圈圈才能被选中,体验不好
使用 label 标签:
<input type="radio" name="demo" id="temp1" /><label for="temp1">单选1</label><input type="radio" name="demo" id="temp2" /><label for="temp2">单选2</label><input type="radio" name="demo" id="temp3" /><label for="temp3">单选3</label><input type="radio" name="demo" id="temp4" /><label for="temp4">单选4</label><input type="radio" name="demo" id="temp5" /><label for="temp5">单选5</label>我们给 input 框设置相应的 id ,label 标签的 for 属性必须对应相应的id。这样当我们点击相应的文字时也是可以被选中的,所以这样的 input 框大大增加了用户体验性。
使用 label 嵌套式标签:
<label><input type="radio" name="demo" />单选1</label><label><input type="radio" name="demo" />单选2</label><label><input type="radio" name="demo" />单选3</label><label><input type="radio" name="demo" />单选4</label><label><input type="radio" name="demo" />单选5</label>为了开发效率我们可以使用第3种,以嵌套的方式来使用,这样我们不用为设置 id 名字而发愁,也不用设置 label 标签中的 for 属性了。
06 | axios 拦截器#
axios拦截器
axios作为网络请求的第三方工具, 可以进行请求和响应的拦截
通过create创建了一个新的axios实例
// 创建了一个新的axios实例const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, // 请求的基地址: process.env, 环境变量 timeout: 5000 // 超时时间})请求拦截器
请求拦截器主要处理 token的统一注入问题
// axios的请求拦截器service.interceptors.request.use( config => { // do something before request is sent
if (store.getters.token) { // let each request carry token // ['X-Token'] is a custom headers key // please modify it according to the actual situation // 添加 token 到请求头 config.headers['X-Token'] = getToken() } return config }, error => { // do something with request error console.log(error) // for debug return Promise.reject(error) })响应拦截器
响应拦截器主要处理 返回的数据异常 和数据结构问题
// 响应拦截器service.interceptors.response.use( response => { // 结构参数 const res = response.data
// if the custom code is not 20000, it is judged as an error. if (res.code !== 20000) { Message({ message: res.message || 'Error', type: 'error', duration: 5 * 1000 }) if (res.code === 50008 || res.code === 50012 || res.code === 50014) { // to re-login MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { confirmButtonText: 'Re-Login', cancelButtonText: 'Cancel', type: 'warning' }).then(() => { store.dispatch('user/resetToken').then(() => { location.reload() }) }) } return Promise.reject(new Error(res.message || 'Error')) } else { return res } }, error => { console.log('err' + error) // for debug Message({ message: error.message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) })这里为了后续更清楚的书写代码,我们将原有代码注释掉,换成如下代码
// 导出一个axios的实例 而且这个实例要有请求拦截器 响应拦截器import axios from 'axios'const service = axios.create() // 创建一个axios的实例service.interceptors.request.use() // 请求拦截器service.interceptors.response.use() // 响应拦截器export default service // 导出axios实例