在做项目的过程中,目前主要遇到了以下几个问题:
一.样式问题
1.样式中使用scoped的问题:
主要表现在从一个页面跳到另一个页面时,第二个页面的样式不能正确显示,通过刷新才能恢复页面的预定样式。
究其原因,是因为如果浏览器在加载了上一个页面的样式时,在跳到第二个页面时,css样式文件是懒加载的,上一
个页面的样式还是会作用到当前的页面,尤其是使用了组件框架时,当大量的以标签作为选择器的样式存在时,就会
使页面产生混乱。
2.解决方案
<1>所有页面统一在style标签内使用scoped属性,避免页面间的相互影响。
添加scoped之后,实际上vue在背后做的工作是将当前组件的节点添加一个像data-v-1233这样唯一属性的标识,当然也会
给当前style的所有样式添加[data-v-1233]。这样的话,就可以使得当前样式只作用于当前组件的节点。
优点:可以有限避免页面样式错乱的问题
缺点:代码复用率低
<2>使用统一的公共样式,在公共样式的基础上给页面添加单独样式。
<3>适当使用行内标签
二.过滤器的问题
在使用Vue过滤器的过程中出现了这样一个问题,需要将电话号码格式化为344的格式,在过滤器中这样写
formatTelNum (value){
let temp = value.split("")........
……
}
一运行就会报undefined的错误,解决的方法是在method中定义格式化电话号码的方法。
三.vue父子组件通讯中传值得一些问题
在Vue父子组件通讯的过程中可能遇到下面的问题:
当父组件中想要传递给子组件的值为异步获取到的时,即使在父组件的created(mounted)中就调用这个异步函数,在子
组件beforeUpdated钩子前都是拿不到这个传递过来的值得,如果想要在子组件页面渲染之前就要使用到这个值,必须在子组件的
标签中使用v-if或者v-show。在父组件想要传递的值还没有获取到之前,使子组件的v-if为false,当异步函数完成时设置为true,即可在
子组件的created钩子中拿到需要传递的值。
v-if和v-show的区别:
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
四.vue钩子
beforeCreate
类型:
Function
-
详细:
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created
类型:
Function
-
详细:
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,
$el
属性目前不可见。
beforeMount
类型:
Function
-
详细:
在挂载开始之前被调用:相关的
render
函数首次被调用。该钩子在服务器端渲染期间不被调用。
mounted
类型:
Function
-
详细:
el
被新创建的vm.$el
替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当mounted
被调用时vm.$el
也在文档内。注意
mounted
不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉mounted
:mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}该钩子在服务器端渲染期间不被调用。
beforeUpdate
类型:
Function
-
详细:
数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
该钩子在服务器端渲染期间不被调用。
updated
类型:
Function
-
详细:
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
注意
updated
不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick 替换掉updated
:updated: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been re-rendered
})
}该钩子在服务器端渲染期间不被调用。
activated
类型:
Function
-
详细:
keep-alive 组件激活时调用。
该钩子在服务器端渲染期间不被调用。
deactivated
类型:
Function
-
详细:
keep-alive 组件停用时调用。
该钩子在服务器端渲染期间不被调用。
beforeDestroy
类型:
Function
-
详细:
实例销毁之前调用。在这一步,实例仍然完全可用。
该钩子在服务器端渲染期间不被调用。
destroyed
类型:
Function
-
详细:
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
该钩子在服务器端渲染期间不被调用。
errorCaptured
2.5.0+ 新增
类型:
(err: Error, vm: Component, info: string) => ?boolean
-
详细:
当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回
false
以阻止该错误继续向上传播。你可以在此钩子中修改组件的状态。因此在模板或渲染函数中设置其它内容的短路条件非常重要,它可以防止当一个错误被捕获时该组件进入一个无限的渲染循环。
错误传播规则
默认情况下,如果全局的
config.errorHandler
被定义,所有的错误仍会发送它,因此这些错误仍让会向单一的分析服务的地方进行汇报。如果一个组件的继承或父级从属链路中存在多个
errorCaptured
钩子,则它们将会被相同的错误逐个唤起。如果此
errorCaptured
钩子自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的config.errorHandler
。一个
errorCaptured
钩子能够返回false
以阻止错误继续向上传播。本质上是说“这个错误已经被搞定了且应该被忽略”。它会阻止其它任何会被这个错误唤起的errorCaptured
钩子和全局的config.errorHandler
。
五.、$nextTick
这个问题可以说是最容易被忽略有最容易令人焦头烂额的了,先上案例:
<el-table
stripe
ref="multipleTable"
:data="vendorList"
tooltip-effect="dark"
style="width: 100%"
@select-all="selectAll"
@selection-change="handleSelectionChange">
<el-table-column type="selection">
</el-table-column>
<el-table-column prop="vendorNum" label="设备编号">
</el-table-column>
<el-table-column prop="vendorModelName" label="设备型号">
</el-table-column>
<el-table-column prop="nickName" label="点位昵称" show-overflow-tooltip>
</el-table-column>
<el-table-column label="当前版本"> </el-table-column>
</el-table>
现有以上这段代码,表格第一列是CheckBox,场景是在表格数据载入之前,和现有数据(vendorNum)比对,如果
vendorNum存在,在相应的CheckBox打上对号。实现的方法很简单,就是在请求回来数据之后调用这个函数:
//通过和请求到数据比较vendorId,设置相应状态为选中
setSelectedStatus(){
let temp = {};
this.selectedVendorList.vendorNumIds.forEach(item=>{
temp[item.num] = item;
this.multipleSelection.push({vendorNum:item.num,vendorId:item.id});
});
for(let i = 0, l = this.vendorList.length; i < l; i++){
let res = this.vendorList[i];
if(temp[res.vendorNum]){
this.$refs.multipleTable.toggleRowSelection(this.vendorList[i]);
}
}
},
这样做的结果是,相应的选项CheckBox是选中的状态,但渲染的结果是未选中。这就要用到VUE里的nextTick了。
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。
$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM。
于是解决的方法如家下:
const list = await getVendorList(data);
if(list.status){
this.vendorList = list.data.items;
this.totalPage = list.data.totalCount;
}else{
this.$message({
type:"error",
message:"数据获取失败"
})
}
//保证在DOM更新之后进行数据比对
this.$nextTick(function(){
this.setSelectedStatus();
});
运行,一切OK!
六.Popover 弹出框
官方文档使用方法如下:
<el-popover ref="popover1" placement="top-start" title="标题" width="200" trigger="hover" content="这是一段内容,这是一段内容,这是一段内容,这是一段内容。"> </el-popover>
<el-button v-popover:popover1>hover 激活</el-button>
通常情况狂下这种用法中规中矩,没有任何问题,但是在表格中,尤其是需要渲染一个数组的数据时用这种方法就会产生一大堆报错,因为和ref和id一样,都是独一无二的。此时
需要用如下方法:
<el-table-column label="商品名称">
<template slot-scope="scope">
<el-popover
placement="right"
width="400"
trigger="hover">
<el-table :data="scope.row.groups">
<el-table-column width="150" label="商品">
<template slot-scope="scope1">
<span style="cursor: pointer;" @click="linkDetails(scope1.row)">{{scope1.row.goodsGroupName}}</span>
</template>
</el-table-column>
<el-table-column width="100" property="amount" label="数量"></el-table-column>
<el-table-column width="300" property="productPrice" label="价格"></el-table-column>
</el-table>
<span slot="reference" style="cursor: pointer;" @click="linkDetails(scope.row)">{{scope.row.goodsGroupName}}</span>
</el-popover>
</template>
</el-table-column>
将触发el-popover显示的内容放在el-popover组件中的插槽中,用一个reference的具名slot ,就可以解决这个问题。