vue使用过程中的一些注意事项

记录下初学vue遇到的问题和注意事项

  • 父组件传给子组件的值在子组件中不能被修改
    • 所以v-model中不应该直接使用父组件传过来的值
    • 应在子组件中使用watch监听父组件传的值,变化时拷贝到子组件data中,而子组件的v-model应该使用子组件data中的值

输入不了/输入一半焦点丢失 考虑初始赋值问题

  • 输入框出现输入问题时,首先考虑是不是初始赋值没给(即null或者undefined)

v-show 不支持 template 元素与 v-else

v-show

不推荐在同一元素上使用 v-if 和 v-for

列表渲染

computed 和 watch 的区别

  • computed是缓存数据的,通过他计算的数据不能被改变,所以不能在model中使用
  • watch是监听,可以改变

watch对首次放入数据的监听

  • watch监听对第一次放入数据时是不监听的,加上immediate能解决这个问题,即立即监听

ajax请求不到数据时

  • 注意检查请求标头里content-type看看时json还是x-www-form-urlencoded,如果时后者,则请求时参数里多加一个'form'

methods 与 箭头函数

  • methods里别用箭头函数,函数内部才用箭头函数,防止this丢失!

路径问题

  • /xxx/xxx是绝对路径。
  • 经过webpack配置@/abc/111,相当于本地的src/abc/111和线上的线上地址.com/abc/111
  • 如果路径在字符串内(如url()内)则需要~@/xxx/xxx才能达到@的效果,但是~和下面的配置无关,只是起到转译的作用,告诉机器@是地址src而不是字符串的效果。
  • 配置如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // vue.config.js内
    config.resolve.alias
    .set('~', resolve('./'))
    .set('@', resolve('src'))
    .set('@assets',resolve('src/assets'))
    .set('@utils', resolve('src/utils'))
    .set('@api', resolve('src/api'))
    .set('@css', resolve('src/css'))
    .set('@components', resolve('src/components'))
    .set('@views', resolve('src/views'))
    .set('@router', resolve('src/router'))
    .set('@store', resolve('src/store'))
    .set('@mixins', resolve('src/mixins'))

图片路径的问题

  • 参考vue中img的src动态赋值(本地图片的路径)中“require方法”
  • 例子:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 错误示范:
    <img :src="images/icon-basic.png"/>
    // npm run dev 或者npm run build之后,解析到的地址是http://localhost:1644/images/icon-basic.png,这是找不到的
    // 因为在webpack中会将图片来当做模块来用,图片被webpack后的路径都会被解析为/static/img/[filename].png,完整地址为localhost:1644/static/img/[filename].png

    // 解决方法:
    // 由于src里无法使用url的@相关配置,所以使用require将图片当成模块先引进来,再绑定
    <img :src="require('@/images/icon-basic.png')"/>
    // webpack解析后的src路径为 'img/icon-basic.04735a2f.png'
    // http://localhost:1644/img/icon-basic.04735a2f.png
  • 问题描述: img的src属性直接绑定图片路径,然而图片加载失败(src中不能使用~@
  • 原因:
    • 在webpack中会将图片来当做模块来用,图片被webpack解析后的路径都会被解析为/static/img/[filename].png,完整地址为localhost:1644/static/img/[filename].png
    • 而直接使用:src="images/icon-basic.png",经过npm run dev 或者npm run build之后,webpack解析到的地址是http://localhost:1644/images/icon-basic.png,这是找不到的
  • 解决方法1:使用require
    • 使用require将图片当成模块先引进来,再绑定
    • 这样npm run dev webpack解析后的src路径为 ‘img/icon-basic.04735a2f.png’,就能顺利找到了
  • 解决方法2:将文件放在statics目录下(与src同级)(参考),但是他不能被webpack优化
    • 图片一类的静态文件,可以放在这个static文件夹下
    • 这个文件夹下的文件(夹)会按照原本的结构放在网站根目录下
    • 注意:这样的话必须写成绝对路径images:[{src:”/static/1.png”},{src:”/static/2.png”}]
    • 缺点:放到static里面webpack打包后只会把资源复制到发布目录而不会把小图片优化为base64,所以为了兼顾可以把图片资源优化,所以还是不适合把图片资源放到static

setDate()获取距离今天n天的日期

1
2
3
4
5
6
7
8
9
10
11
12
13
// 获取距离今天n天的日期 +几天后  -几天前
getDateStr: function getDateStr(AddDayCount) {
var dd = new Date();
dd.setDate(dd.getDate() + AddDayCount); //获取AddDayCount天后的日期
var y = dd.getFullYear();
var m = dd.getMonth() + 1; //获取当前月份的日期
var d = dd.getDate();
return y + "-" + m + "-" + d;
},

// 使用
// 获取昨天的日期(假设今天2021-07-14)
getDateStr(-1) // 2021-07-13

父子组件生命周期导致父子组件之间传值的问题 v-if的妙用

  • 问题描述:当父组件在mounted中通过ajax获取值放在data中并通过bind传递给子组件时,如果子组件mounted中要用到这个值就会发现子组件中取到的不是父组件mounted’中获取到的值,这是父子组件生命周期的原因。
  • 思路:让子组件在父组件mounted结束后才渲染
  • 解决方法:给子组件加一个if,当父组件获取值结束后改if为true时子组件才开始渲染

区分react,vue的事件函数

  • react事件处理可参考菜鸟教程
    • react中的事件函数的函数名后不能跟(),且需要bind绑定this指向,传参可在bind()中传也可使用箭头函数(参考 bind()
  • vue的事件处理可参考官方文档
    • vue的事件函数和react不同,是可以直接在事件函数名后跟()的(不跟()也可以),传参也可以直接在()中传递
    • 当然,使用箭头函数传参也是没问题的

js实现页面跳转

  1. location.href="URL"当前窗口直接跳页,可点击回退到上一个页面,注意他是属性不是方法
  2. location.replace("URL")当前窗口直接跳页,不可点击回退到上一个页面
  3. location.assign("URL")location.href相似
  4. window.open("URL")新开窗口

动态样式

class内

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!-- 1 class接收一个表达式 -->
<div :class="isRight ? 'right' : ''""></div>
<div :class="index !== 0 && 'right'"></div>

<!-- 2 class接收一个拼接字符串,假设item.name为 rightItem -->
<div :class="item.name +' el-icon--right'"></div>

<!-- 3 class接收一个对象 -->
<div :class="{ 'right': isRight }"></div>

<!-- 3 class接收一个数组 -->
<div :class="['baseClass', {'right': isRight}]"></div>

<!-- 3 class接收一个方法(返回值为字符串) -->
<div :class="cellClass(可传参)"></div>

---
data: {
isRight: true,
index: 0,
}
methods: {
cellClass(可接收参数) {
if ( xxx) return 'right'
if ( xxx ) return 'baseClass'
return ''
},
}
---
.baseClass {
font-size: 14px
}
.right {
float: right
}
.rightItem el-icon--right {
color: red
}

style内

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- 1 动态样式对象属性 -->
<div :style="{ color: activeColor, 'font-size': fontSize + 'px' }"></div>
<div :style=`width:${leftWidth}px; padding: ${paddingLeft}px;`></div>
<!-- 2 将多个 样式对象 应用到一个元素上-->
<!-- baseStyles 和 overridingStyles 都是data中定义的对象 -->
<div v-bind:style="[baseStyles, overridingStyles]"></div>

---
data: {
activeColor: '#efdbfe',
fontSize: '14',
baseStyles: {
color: 'green',
fontSize: '30px'
},
overridingStyles: {
'font-weight': 'bold'
}
}
// leftWidth和paddingLeft为变量

防抖时timer取不到值的问题

  • 防抖timer不能获取最新值(获取到null),导致无法清除setTimeout,考虑下是不是因为监听在子组件内,timer放 子组件data 导致作用域不够外层(存在每个子组件自己的作用域内了)
  • 解决方法:提到和子组件import同一级,定义一个let timer = null这个位置只会在父组件调用子组件时调用一次,不会因为调用多次调用子组件而定义多个timer,而此时作用域就可针对多个子组件了

,