Vue开发遇到的干货(持续更新中)

/ 前端 / 0 条评论 / 3812浏览

el-select

注意 value为string类型,如果value值为Number类型会造成,回显值显示ID、选择项目后显示ID

html代码

 <el-form-item label="类型"  required>
    <el-select v-model="groupSelectOption" filterable placeholder="选择类别">
        <el-option @click.native="groupSelectOption = item.value" v-for="(item,index) in groupSelectList" :key="index" :label="item.label"  :value="item.value"></el-option>
    </el-select>
  </el-form-item>

错误数据格式

groupSelectOption:1,
groupSelectList:[
    {value:0, label:"类型1"},
    {value:1, label:"类型2"},
    {value:2, label:"类型3"}
]

结果:下来框回显 为 1,预期显示 类型2 ,与预期不符 原因:value类型必须为 string

正确数据格式

groupSelectOption:1,
groupSelectList:[
    {value:"0", label:"类型1"},
    {value:"1", label:"类型2"},
    {value:"2", label:"类型3"}
]

结果: 下拉框回显 类型2

官方文档 2.0

横向分列显示

如下代码,将面板均分为2列。

代表1行; 代表1列 ,一行内分为24小格,每列宽度占比可调整 span

<el-row>
    <el-col :span="12">
        <el-form-item label="列A"  required>
        </el-form-item>
    </el-col>
    <el-col :span="12">
        <el-form-item label="列B" required>
        </el-form-item>
    </el-col>
</el-row>

el-input 的 placeholder无效

placeholder属性在el-input标签上一级的div上,无法显示。经排查是vue.min.js版本低的原因,测试2.5.16版本可以正常使用。 html引入方式

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>

元素显示隐藏

<div title="显示隐藏"   v-if="showTag"></div>

new Vue({
    el: '#app',
    data: {
        showTag:false
    } 
})

element-ui中radio默认选中

<el-radio-group v-model="datatype">
  <el-radio label="system">
  	<el-tooltip placement="top" effect="light">
		<div slot="content">客户系统内部数据.</br>1.需要先配置相关模块,才能选择;</br>2.客户端数据选项与账号权限有关</div>
		<span>系统</span>
	</el-tooltip>
  </el-radio>
  <el-radio label="remote">
     <el-tooltip placement="top" effect="light">
		<div slot="content">通过URL获得的数据.</br>数据格式必须符合对应规则,客户端数据选项与权限无关</div>
		<span>远程</span>
	 </el-tooltip>
  </el-radio>
  <el-radio label="local">
     <el-tooltip placement="top" effect="light">
		<div slot="content">本地文本数据.</br>在下面文本框完成编辑即可.</div>
		<span>本地</span>
	 </el-tooltip>
  </el-radio>
</el-radio-group>

new Vue({
    el: '#app',
    data: {
        datatype:"system"
    } 
})

效果 请输入图片描述

Vue中watch监听对象

坑点1.对象无法监听

监听的几种方式不详细说明,网上很多例子。我遇到的问题是对象{}无法监听,数组[]可以监听。使用deep监听即可,代码如下。

data:{
        formFieldBasic:{}
},
watch:{
	formFieldBasic:{
		handler:function(a,b) {
			console.log(JSON.stringify(a));
			console.log(JSON.stringify(b));
		},
		//immediate: true,	//值变化立即回调
		deep: true	//深度复制
	}
}

坑点2.新旧对象值相同

如下例子 a,b的值始终相同,为最新值。原因是对象为引用类型,a,b引用的堆地址相同均为最新的值。借助 computed 可以解决。代码如下

data:{
        formFieldBasic:{}
},
computed:{
	formFieldBasicW() {
                //此处序列号对象或者深度拷贝对象即可。deepClone是我重新写Object的函数,可以使用JSON.parse(), JSON.stringify() 代替
		return this.formFieldBasic.deepClone();
	}
},
watch:{
	formFieldBasicW:{
		handler:function(a,b) {
			console.log(JSON.stringify(a));
			console.log(JSON.stringify(b));
		},
		//immediate: true,	//值变化立即回调
		deep: true	//深度复制
	}
}

第一个参数 a 为新值 第二个参数 b 为旧值

a,b可以自行定义

动态布局页面(牛牛牛)

如果你想根据后端数据动态布局页面。可以使用component标签+自定义组件。非常简单,非常实用。贴两端代码帮助自己记忆。代码有点乱,如果你也有动态布局的需求,可以联系我一起探讨。

<el-row>
	<component v-for="node in peprops" v-bind:is="'ce-'+node.ctype" :node="node">
		<component v-if="node.childrens!=undefined" v-for="n2 in node.childrens" v-bind:is="'ce-'+n2.ctype" :node="n2">
			<component v-if="n2.childrens!=undefined" v-for="n3 in n2.childrens" v-bind:is="'ce-'+n3.ctype" :node="n3"></component>
		</component>
	</component>
</el-row>

<!-- 引入自定义组件 -->
<head>
	<#include "/selfcomponents.html">
	<script src="${request.contextPath}/statics/js/selfcomponents.js"></script>
</head>

或者

 <!-- 引入模板 -->
 <div id="template"></div>

<!-- 引入自定义组件 -->
<script type="text/javascript">
	$("#template").load("components/flowcomponents.html");
</script>
<script src="components/flowcomponents.js"></script>
<!-- input框 -->
<script type="x-template" id="ce-input">
	<el-col :span="node.span||13">
	<el-form-item :label="node.fieldname" :error="node.errorMessage">
		<el-autocomplete v-if="node.csubtype=='autocomplete'" :name="node.fieldkey" v-model="node.value" :fetch-suggestions="querySearchAsync" :placeholder="node.placeholder" @select="handleSelect" @focus="removeErrorMsg" @blur="customvalidator" :maxlength="node.maxlength||30" show-word-limit :trigger-on-focus="false">
			<template slot-scope="{ item }">
    			<div>{{ item }}</div>
			</template>
		</el-autocomplete>
		<el-input v-else :type="node.csubtype" :name="node.fieldkey" v-model="node.value" :placeholder="node.placeholder" @focus="removeErrorMsg" @blur="customvalidator" :maxlength="node.maxlength||30" show-word-limit></el-input>
	</el-form-item>
	</el-col>
</script>
Vue.component('ce-input', {
	template: '#ce-input', 
	props: ['node'],
	data: function (){
		return {
			options: []
		}
	},
	methods: {
		loadData:function() {
	        return [
	          "三全鲜食(北新泾店)",
	          "Hot honey 首尔炸鸡(仙霞路)",
	          "新旺角茶餐厅",
	          "泷千家(天山西路店)"
	        ];
		},
		querySearchAsync:function(queryString, cb){
	        cb(queryString?this.options.filter(o => {return o.toLowerCase().indexOf(queryString.toLowerCase()) === 0;}):this.options);
		},
		handleSelect:function(item) {
			this.node.value = item;
		},
		removeErrorMsg:function(){
			this.node.doselected(this.node);
			this.node.errorMessage = null;
		},
		customvalidator:function(){
			if(isBlank(this.node.value)){
				if(this.node.isrequired){
					this.node.errorMessage = this.node.fieldname+"不能为空,请您填写.";
					return;
				}
			}else{
				let rules = this.node.rules;
				if(rules&&rules.length>0){
					for(var i=0;i<rules.length;i++){
						if(!eval("/"+rules[i]+"/").test(this.node.value)){
							this.node.errorMessage = "格式错误[" + (this.node.errorprompt||("请输入正确格式"+this.node.fieldname))+"]";
							return;
						}
					}
				}
			}
			this.node.errorMessage = null;
		}
	},
	mounted : function(){
		this.options = this.loadData();
	}
});

强制刷新组件重新渲染

解决方案一

当数据变更后,通过watch 监听,先去销毁当前的组件,然后再重现渲染。使用 v-if 可以解决这个问题

<template>
   <third-comp v-if="reFresh"/>
</template>
 
<script>
   export default{
       data(){
          return {
                reFresh:true,
                menuTree:[]
            }
       },
       watch:{
             menuTree(){
 
                  this.reFresh= false
                  this.$nextTick(()=>{
                    
                    this.reFresh = true
                })
            }
       }
}
</script>

解决方案二

通过vue key 实现,原理官方文档。所以当key 值变更时,会自动的重新渲染。(推荐)

<template>
   <third-comp  :message="menuData"  :key="menuKey"/>
</template>
 
<script>
   export default{
       data(){
          return {
                menuKey:1,
             menuData: "", 
            }
       },
       watch:{
             menuData(){
                ++this.menuKey
            }
       }
}
</script>

真是巨坑啊 v-if 后面使用 key ,在批量切换状态时,报错 undefined key 导致整个页面卡死。 使用v-show可以解决

验证过可以有效解决问题原文链接

方法中传入自定义参数

方法一(适用大多情况)

<!--   a, b, c 为定义参数, ...arguments为默认参数 -->
@click="onClick(a, b, c, ...arguments)"

方法二

<el-upload 
    :on-change="function(file, fileList){return handlechange(file, fileList, scope.row.fieldkey)}" >
</el-upload>

方法一不行就试试方法二

固定列陷阱(组件初始化两次)

<el-table :data="tableRows" border>
	<el-table-column fixed="left" label="操作" width="60">
		<template slot-scope="scope">
			<el-button type="info" icon="el-icon-plus" circle size="small" @click="addRow(scope.$index+1)"></el-button>
			<el-button type="info" icon="el-icon-delete" circle size="small" @click="delRow(scope.$index)"></el-button>
		</template>
	</el-table-column>
	<el-table-column v-for="(item,index) in node.childrens" :prop="item.fieldkey" :label="item.fieldname" :width="item.width * vm.mwconfig[node.fieldkey].perunit">
		<template slot-scope="scope">
			<ce-table_cell :row="scope.row" :column="scope.column" :index="scope.$index" :pindex="pindex" :cellNode="options[scope.$index].cnodes[item.fieldkey]" :parentNode="options[scope.$index].node"></ce-table_cell>
		</template>
	</el-table-column>
</el-table>

1.以上 fixed="left" 会导致后面的 v-for="(item,index) in node.childrens"执行两次

  1. 中的expand模板中嵌套一个table,这个table会被渲染两次,父组件table里面具有fixed属性的table会这样,请删掉它 ,找很久才发现