Skip to main content

小知识点

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效果

css_01

解决办法:

// 方式一.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实例