1.问题描述,就是我一个下拉项串行并行切换的时候,同时也会切换form的rules,而切换之后,会自动触发一次validate的校验,导致页面没提交,只是切换
下拉,却出现了校验一次的情况,rules的切换是根据执行方式的变化而变化的 简单来说就是我的表单验证是动态的,可能多出来几个必填的,或者少几个必填的
会根据一些选项决定
解决方法是在执行方式 select onchange方法里调用一下 this.$nextTick(() => {
self.$refs.stepRef2.clearValidate('timeout')
})
清除一下表单验证,注意要在nexttick中执行,不然没效果
2.element的radio,label默认只能绑定string,也就是说
<el-radio v-model="stepForm4.builtTask" label=“false“>否</el-radio>
<el-radio v-model="stepForm4.builtTask" label=“true“>是</el-radio>
builtTask: false,表单里的这个值,必须也写成 builtTask: "false",字符串类型,不然不会默认显示否,对不上
这时候可以这样,就能布尔值对上了,加冒号,动态传
<el-radio v-model="stepForm4.builtTask" :label=false>否</el-radio>
<el-radio v-model="stepForm4.builtTask" :label=true>是</el-radio>
builtTask: false,这样就ok
3.table实现单选
这篇博客 https://blog.csdn.net/BrightLD/article/details/90049972?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm=1001.2101.3001.4242
然后再
/*隐藏表头复选框*/
::v-deep .el-table__header .el-table-column--selection .cell .el-checkbox {
display:none}
4.遇到一个问题,有些感悟
就是table里有个:render-header=函数 放在el-table-column上可以渲染这一行的表头,通过createelement函数创建元素
结果使用的使用,一直出不来,后来发现是多写了一个括号
所以以后找错误,一定要先看看是不是语法写错了,然后再看逻辑或者使用错误
<template><div class="steptemp"><!--脚本与组件 步骤调节组件 通过标示区分是调节脚本还是组件--><!--头部toolbars--><div class="toolbars"><ul><!--这里的下面三个调用弹框 传编辑,复制,删除所需要的数据就行了,这个数据,这里单独发请求到了--><li @click="handleEvent('tableEdit')"><i class="el-icon-edit"></i><span>编辑</span></li><li @click="handleEvent('tableCopy')"><i class="el-icon-document-copy"></i><span>复制</span></li><li @click="handleEvent('tableDel')"><i class="el-icon-delete"></i><span>删除</span></li><li><i class="el-icon-upload2"></i><span>导入</span></li></ul><ol><li><el-button size="mini" style="margin-bottom:5px;" type="primary" @click="handleSaveStep">保存</el-button></li><li @click="toStepTemp"><i class="el-icon-back"></i></li></ol></div><!--信息数据--><div class="info"><h2>{{stempConfig.moduleName}}</h2><ul class="info_tag"><li v-for="item in stempConfig.tags">{{item}}</li></ul><div class="info-detail"><p>创建人:{{stempConfig.creator}}</p><p>所属分组:{{currentDirectoryName}}</p><p>更新时间:{{stempConfig.updateTime}}</p></div></div><!--表格部分--><div class="temp-table"><div class="temp-table-top"><div class="el-dropdown-link"><el-button type="primary" icon="el-icon-plus" class="btn_new_group" @click="handleStepAdd">添加执行步骤</el-button></div></div><div class="temp-table-bottom"><el-table ref="dragTable" :data="tableData" :header-cell-style="{background:'#F8F2F2'}" class="data_table" style="width: 100%"border row-key="stepId"><el-table-column :render-header="(h,obj) => renderTooltip(h, obj)" v-for="(item, index) in col" :key="`col_${index}`" header-align="center"align="center" :width="item.formLabelWidth?item.formLabelWidth:'auto'" :prop="item.prop" :label="item.label"><template slot-scope="scope"><div class="allowDrag" v-if="item.type=='sort'" style="text-align: center;"><i class="el-icon-sort" style="cursor:pointer;"></i></div><div v-else-if="item.type=='operation'" style="text-align: center;display: flex;justify-content: space-between"><!--增加和删除按钮--><i size="small" class="el-icon-circle-plus-outline fs20" @click="handleStepAdd"></i><i class="el-icon-remove-outline fs20" @click="handleStepDelete(scope.$index)"></i></div><div v-else-if="item.type=='selectEvent'"><el-select style="width:100%" v-model="scope.row.event"><el-option v-for="item1 in eventList" :key="`${item1.value}event`" :label="item1.value" :value="item1.value"><span style="float: left">{{ item1.value }}</span><span style="float: right; color: #8492a6; font-size: 13px">{{ item1.label }}</span></el-option></el-select></div><div v-else-if="item.type=='selectAlert'"><el-select style="width:100%" v-model="scope.row.alertRule"><el-option v-for="item2 in alertRuleList" :key="`${item2.value}alertRule`" :label="item2.value" :value="item2.value"><span style="float: left">{{ item2.value }}</span><span style="float: right; color: #8492a6; font-size: 13px">{{ item2.label }}</span></el-option></el-select></div><div class="event_param" v-else-if="item.type=='triplingParam'"><ul v-show="scope.row.isEventParamShow"><li @mousedown="handleParam('comParam',scope.$index,'triplingParam')">引入公共参数</li><li>引入步骤参数</li><li @mousedown="handleParam('paramconstr',scope.$index,'triplingParam')">参数构造器</li></ul><el-input @input="handleParamInput(scope.$index)" @blur="handleParamBlur(scope.$index)" @focus="handleParamFocus(scope.$index)"v-model="scope.row.eventParam"></el-input></div><div class="event_param" v-else-if="item.type=='singleParam'"><ul v-show="scope.row.isPositionParamShow"><li @mousedown="handleParam('comParam',scope.$index,'singleParam')">引入公共参数</li><!--<li>引入步骤参数</li>--></ul><el-input @input="handleParamInput1(scope.$index)" @blur="handleParamBlur1(scope.$index)" @focus="handleParamFocus1(scope.$index)"v-model="scope.row.locationProperty"></el-input></div><span v-else-if="item.type=='inputNum'"><el-input-number style="width: 100px;" placeholder="请输入等待时间" v-model="scope.row.latencyTime" controls-position="right" :min="0" :max="60"></el-input-number><!--<el-input v-model="scope.row[item.prop]" oninput="value=value.replace(/[^\d]/g,'')"></el-input>--></span><span v-else><el-input ondragstart="return false" v-model="scope.row[item.prop]"></el-input></span></template></el-table-column></el-table></div></div><!--公共参数弹框--><CommonParam :isComParamShow="isComParamShow" @commonParamClick="commonParamClick"></CommonParam><!--参数构造器弹框--><ParamConstructor :isParamConstrShow="isParamConstrShow" @paramConstructorClick="paramConstructorClick"></ParamConstructor></div></template>
<script lang="ts">import { Component, Vue, Prop, Watch } from 'vue-property-decorator';import { ApiWebComponentService } from 'mone-test/services';import Sortable from 'sortablejs'import CommonParam from 'mone-test/components/commonDialog/commonParam/index.vue'import ParamConstructor from 'mone-test/components/commonDialog/paramConstructor/index.vue'@Component({name: 'StepTempWeb',components: {CommonParam, ParamConstructor}})export default class StepTemp extends Vue {/*** props ***/// 通过一个统一props来确定,所以得操作是组件还是脚本@Prop({ type: Object, default: () => { return {}; } }) stepTempInfo;@Prop({ type: String, default: () => { return ''; } }) currentDirectoryName;// id需要我传时间戳,如果是新增,那么就传个时间戳// 如果是编辑再保存,就不用再传时间戳,就传它请求到底传来的那个id// 也就是通过他本来有没有id来判断是新增还是编辑tableData: object[] = [];stempConfig: object = {createTime: "yyyy-MM-dd HH:mm:ss",creator: "string",deleted: true,directoryPath: "string",directoryName: "",id: 0,key: "string",moduleDesc: "string",moduleName: "string",moduleTags: "string",rewriter: "string",tags: ["string"],updateTime: "yyyy-MM-dd HH:mm:ss",versionId: 0,webModules: [null]}total: number = 0stepStartFormVisible: boolean = false;formLabelWidth: string = '120px'col: object[] = [{label: '顺序',type: 'sort',formLabelWidth: '50px'},{label: '步骤名称',prop: 'name',formLabelWidth: '130px'},{label: '事件',prop: 'event',type: 'selectEvent',formLabelWidth: '130px',// selectOption:this.eventList},{label: '定位属性',prop: 'locationProperty',type: 'singleParam',formLabelWidth: '150px'},{label: '参数',prop: 'eventParam',type: 'triplingParam',formLabelWidth: '300px'},{label: '等待时间(s)',prop: 'latencyTime',type: 'inputNum',formLabelWidth: '112px'},{label: '断言规则',prop: 'alertRule',type: 'selectAlert',formLabelWidth: '130px',// selectOption:this.alertRuleList},{label: '预期结果',prop: 'expect',formLabelWidth: '130px'},{label: '设置变量',prop: 'var',formLabelWidth: '130px'},{label: '操作',type: 'operation',formLabelWidth: '60px'},];operation: Number = 1eventList: object[] = [{ label: "获取html标签文本值", value: "getText" },{ label: "获取html标签属性", value: "getAttribute" },{ label: "获取html标签内部html文本", value: "getInnerHTML" },{ label: "获取html标签内部文本", value: "getInnerText" },{ label: "清空输入框", value: "clear" },{ label: "向输入框输入内容", value: "fill" },{ label: "鼠标单击", value: "mouseClick" },{ label: "鼠标双击", value: "mouseDblClick" },{ label: "鼠标悬停", value: "mouseHover" },{ label: "标签元素聚焦", value: "mouseFocus" },{ label: "判断元素是否可用(反义isDisabled)", value: "isEnabled" },{ label: "判断元素是否禁用", value: "isDisabled" },{ label: "判断元素是否可编辑", value: "isEditable" },{ label: "判断元素是否可视化(反义isHidden)", value: "isVisible" },{ label: "判断元素是否隐藏", value: "isHidden" },{ label: "单选框或复选框选中", value: "check" },{ label: "单选框或复选框取消选中", value: "uncheck" },{ label: "判断单选框或复选框选中状态", value: "isChecked" },{ label: "模拟键盘输入", value: "type" },{ label: "模拟键盘按下,通常是快捷键", value: "press" },{ label: "上传文件,输入是完整文件路径或相对路径", value: "upload" },{ label: "下载文件,输入下载的指定目录", value: "download" },{ label: "使用JavaScript", value: "executeJS" },{ label: "打开一个浏览器页签", value: "pageOpen" },{ label: "关闭一个浏览器页签", value: "pageClose" },{ label: "页面重新加载", value: "pageReload" },{ label: "获取当前页签标题", value: "getTitle" },{ label: "对话框点击确定", value: "dialogConfirm" },{ label: "对话框点击取消", value: "dialogDismiss" },{ label: "对话框输入文本", value: "dialogAccept" },{ label: "页面前进", value: "goForward" },{ label: "页面回退", value: "goBack" },{ label: "页面滚动(模拟滚动条滚动)", value: "pageTap" },{ label: "截图,输入是完整文件路径或相对路径", value: "pageScreenshot" },{ label: "清除全局缓存", value: "cacheClear" }]alertRuleList: object[] = [{ label: '包含', value: 'contain' },{ label: '等于[=]', value: 'equal' },{ label: '不等于[!=]', value: 'notEqual' }]isComParamShow: object = { flag: false }isParamConstrShow: object = { flag: false }currentParamType: string = "param" //默认事件参数输入框吧currentTableIndex: number = 0;currentTableInputType: string = '';constructor() {super()}mounted() {// const self = this as any// this.$nextTick(()=>{// self.rowDrop();// })}created() {if (this.stepTempInfo && this.stepTempInfo.row && this.stepTempInfo.row.id) {this.getWebModuleSingle()}}paramConstructorClick(param) {const self = this as anyif (this.currentTableInputType == 'singleParam') {self.$set(self.tableData[self.currentTableIndex], 'locationProperty', param)} else if (this.currentTableInputType == 'triplingParam') {self.$set(self.tableData[self.currentTableIndex], 'eventParam', param)}}commonParamClick(param) {const self = this as any// 根据当前index,填充进table里if (this.currentTableInputType == 'singleParam') {self.$set(self.tableData[self.currentTableIndex], 'locationProperty', param)} else if (this.currentTableInputType == 'triplingParam') {self.$set(self.tableData[self.currentTableIndex], 'eventParam', param)}}handleParamBlur(index) {const self = this as anyself.$set(self.tableData[index], 'isEventParamShow', false)self.tableData = self.tableData.concat()}handleParamInput(index) {const self = this as anythis.$set(self.tableData[index], 'isEventParamShow', false)}handleParamFocus(index) {const self = this as anyself.$set(self.tableData[index], 'isEventParamShow', true)self.tableData = self.tableData.concat()}handleParamBlur1(index) {const self = this as anyself.$set(self.tableData[index], 'isPositionParamShow', false)self.tableData = self.tableData.concat()}handleParamInput1(index) {const self = this as anythis.$set(self.tableData[index], 'isPositionParamShow', false)}handleParamFocus1(index) {const self = this as anyself.$set(self.tableData[index], 'isPositionParamShow', true)self.tableData = self.tableData.concat()}getWebModuleSingle() {const self = this as anyApiWebComponentService.getWebModuleSingle({ id: self.stepTempInfo.row.id }).then(res => {if (res.code == 200) {if (res.data.id) {// 这里做一个判断,如果有至少一条数据,那么tabledata中就不放// 默认的一条空数据,否则默认放一条空数据// 还有一个操作,就是查询的时候要给,每个数据两个属性,用于控制,参数选项是显示还是隐藏,// 对应的,保存的时候,也要删除这两个属性self.total = res.data.totalself.stempConfig = Object.assign({}, res.data)if (res.data.steps && res.data.steps.length != 0) {// self.tableData = res.data.steps.concat()self.tableData = res.data.steps.map(el => {el.isPositionParamShow = falseel.isEventParamShow = falsereturn el}).concat()} else {self.tableData = [{name: '',event: 'getText',locationProperty: '',eventParam: '',latencyTime: 0,alertRule: null,expect: '',var: '',isPositionParamShow: false,isEventParamShow: false}]}if (res.data.steps) {self.tableData = res.data.steps.concat()}}}}).catch(err => {self.toStepTemp()})}toStepTemp() {const self = this as any// 返回的时候要保存self.handleSaveStep('back')this.$emit('toStepTemp', true, self.stepTempInfo.row.directoryPath)}handleEvent(funcName) {let obj = { row: {} }obj.row = Object.assign({}, this.stempConfig)this.$parent[funcName](obj)}// 行拖拽rowDrop() {const _this = this as anyconst table = _this.$refs.dragTable;const tbody = table.$el.querySelector('.el-table__body-wrapper tbody');Sortable.create(tbody, {handle: ".allowDrag",onEnd({ newIndex, oldIndex }) {const currRow = _this.tableData.splice(oldIndex, 1)[0]_this.tableData.splice(newIndex, 0, currRow)}})}handleParam(diaType, index, inputType) {// 点击的时候,记录当前的index,用以确定参数放在哪一行this.currentTableIndex = index// 还要记录当前input类型,是三个的还是一个的this.currentTableInputType = inputTypeif (diaType == 'paramconstr') {this.isParamConstrShow['flag'] = true} else if (diaType == 'comParam') {this.isComParamShow['flag'] = true}}handleStepAdd() {const self = this as anyself.tableData.push({name: '',event: 'getText',locationProperty: '',eventParam: '',latencyTime: 0,alertRule: null,expect: '',var: '',isPositionParamShow: false,isEventParamShow: false})}handleStepDelete(index) {const self = this as anyself.tableData.splice(index, 1)}// 点击保存,保存步骤handleSaveStep(type) {// 有个校验,如果只有一条全空的数据// 那么也请求接口,但是啥也不传// 点击保存的时候,全为空的数据不传// 传过去的时候,记得吧query里的那两个属性删除const self = this as anylet query = self.tableData.map(el => {delete el.isPositionParamShowdelete el.isEventParamShowel.stepId = el.stepId ? el.stepId : new Date().getTime()return el})let myquery = { steps: query, id: self.stepTempInfo.row.id }ApiWebComponentService.saveSteps(myquery).then(res => {if (res.code == 200) {// 成功之后返回表格type == 'back' ? '' : self.toStepTemp()}}).catch(err => {type == 'back' ? '' : self.toStepTemp()})}// 渲染表头renderTooltip(h, { column, $index }) {const self = this as any;if (column.label=='设置变量') {return h('el-tooltip', // 标签的名称{props: { //标签的参数 通过不同的标签 显示不同的文字content: (function () {//如何拿到 label的文字?? 通过column.label来拿// let label = column.label// switch (label) {// case '拦截状态':// return '我是提示文字'// break// case '提示2':// return '提示文字2'// break// case '提示3':// return '提示文字3'// break// }return '在使用事件参数时,可以将输入的值保存为全局变量,'+ '后面组件的步骤引用,引用的格式为"$value"'})(),placement: 'top',// effect: "light", // 默认为黑色主题},///下面的意思是往el-tooltip 标签里面添加内容 column.label(拿到自己定义的显示内容: 拦截状态 ) domProps: {innerHTML: column.label + '<span class="el-icon-question" style="color: #409eff;margin-left:10px "></span>'}},[h('span')])}// if (!cfg.filterTyle || cfg.filterTyle == '') {return h('div', { style: 'display: flex;' }, [h('div', {domProps: {innerHTML: column.label}}),]);}}</script>
<style scoped lang="scss">.steptemp {flex: 1;overflow: auto;.toolbars {border-bottom: 1px solid #ccc;display: flex;justify-content: space-between;align-items: center;ul {display: flex;li {margin: 0 10px;cursor: pointer;}}ol {display: flex;align-items: center;li {margin: 0 10px;cursor: pointer;}}}.info {border-bottom: 1px solid #ccc;&_tag {display: flex;li {padding: 2px;height: 22px;background-color: rgba(236, 245, 255, 1);border-radius: 2px;font-size: 12px;margin-right: 5px;}}h2 {font-family: '微软雅黑 Bold', '微软雅黑 Regular', '微软雅黑';font-weight: 700;font-style: normal;font-size: 15px;}&-detail {display: flex;p {font-size: 12px;color: #7F7F7F;margin-right: 10px;}}}.temp-table {margin-top: 5px;&-top {padding: 10px 0 10px 10px;border: 1px solid #ccc;.btn_new_group {background: #0EAFC0;border-color: #0EAFC0;padding: 6px;font-size: 12px;border-radius: 0;margin: 0;}.btn_new_group:hover {background: #0adcf3;border-color: #0adcf3;}}&-bottom {.data_table {max-width: 1100px;width: 100%;::v-deep th {/*background-color: #f2eded;*/}::v-deep td {/*transition: background-color .25s ease;*/position: relative!important;}.event_param {/*position: relative;*/ul {position: absolute;left: 50%;top: -2px;transform: translateX(-50%);display: flex;z-index: 1;li {margin-right: 5px;font-weight: 250;font-style: normal;font-size: 11px;text-align: center;width: 80px;padding: 0 4px;height: 20px;line-height: 20px;background-color: rgba(0, 191, 191, 1);border: none;border-radius: 4px;box-shadow: 2px 2px 2px rgba(0, 191, 191, .35);font-family: '微软雅黑 Light', '微软雅黑 Regular', '微软雅黑';color: #FFFFFF;cursor: pointer;}}}}.temp-count {background-color: #F2F2F2;p {margin: 0;height: 45px;line-height: 45px;padding-right: 10px;font-family: 'Arial Normal', 'Arial';font-weight: 400;font-style: normal;font-size: 13px;letter-spacing: normal;color: #333333;text-align: right;}}}}.fs20 {font-size: 20px;cursor: pointer;}}
</style>
5.关于日期选择器的禁选的两种需求
一个是以当前时间为准,只能选择前后一个月的,别误会了,这个的功能是,它只会把当前时间,也就是new Date()前后一个月禁止,而不是选中的日期禁止
<template><div>Compute--{{ compute }}<div><el-date-pickerv-model="dateStr"type="daterange"range-separator="至"start-placeholder="开始日期"end-placeholder="结束日期":picker-options="pickerOptions"/></div></div>
</template>
<script>
export default {props: {compute: {type: Array}},data: () => {let _minTime = nulllet _maxTime = nullreturn {dateStr: '',pickerOptions: {disabledDate(time) {let timeRange = 30 * 24 * 60 * 60 * 1000_minTime = new Date().getTime() - timeRange_maxTime = new Date().getTime() + timeRangereturn time.getTime() < _minTime || time.getTime() > _maxTime// if (_minTime && _maxTime) {// return time.getTime() < _minTime || time.getTime() > _maxTime// }},shortcuts: [{text: '最近一周',onClick(picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)picker.$emit('pick', [start, end])}}, {text: '最近一个月',onClick(picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)picker.$emit('pick', [start, end])}}, {text: '最近三个月',onClick(picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)picker.$emit('pick', [start, end])}}]}}},created() { },methods: {}
}
</script>
<style scoped>
</style>
一个是选择日期的时候,根据当前所选,进行动态禁止选中前后一个月的
<template><div>Compute--{{ compute }}<div><el-date-pickerv-model="dateStr"type="daterange"range-separator="至"start-placeholder="开始日期"end-placeholder="结束日期":picker-options="pickerOptions"/></div></div>
</template>
<script>
export default {props: {compute: {type: Array}},data: () => {let _minTime = nulllet _maxTime = nullreturn {dateStr: '',pickerOptions: {onPick(time) {if (!time.maxDate) {let timeRange = 30 * 24 * 60 * 60 * 1000_minTime = time.minDate.getTime() - timeRange_maxTime = time.minDate.getTime() + timeRange} else {_minTime = _maxTime = null}},disabledDate(time) {// let timeRange = 30 * 24 * 60 * 60 * 1000// _minTime = new Date().getTime() - timeRange// _maxTime = new Date().getTime() + timeRange// return time.getTime() < _minTime || time.getTime() > _maxTimeif (_minTime && _maxTime) {return time.getTime() < _minTime || time.getTime() > _maxTime}},shortcuts: [{text: '最近一周',onClick(picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)picker.$emit('pick', [start, end])}}, {text: '最近一个月',onClick(picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)picker.$emit('pick', [start, end])}}, {text: '最近三个月',onClick(picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)picker.$emit('pick', [start, end])}}]}}},created() { },methods: {}
}
</script>
<style scoped>
</style>
这个日期选择器的禁止的内部实现,只不过是执行了这个函数,我们来看看它对这个函数应该是做了什么,我想了想,应该是这么做的,我以第二种展开来讲
传函数进来,也就是pickeroptions里的disabled以及onpick函数,首先,点击时间,onpick参数是当前选中时间,执行之后得到mintime,这样,确认最小范围,之后点第二个日期的时候,又能得到maxtime,确认最大时间范围,这样diabled就能够执行了(因为里面写了if (_minTime && _maxTime)才执行),里面有判断,要maxtime和mintime同时存在,才执行,然后所有日历日期都会传自己的时间进来执行它,得到ture或者false,就能知道自己这个日期时间是不是需要禁止的日期了,那么如何显示禁止和隐藏禁止呢,我觉得,这个函数传进来之后,放在一个computed里面,然后,在日历v-for渲染的时候,disable的就设置为这个computed,这样就行了
第二种,就只是执行disabled,不过执行的方式还是我说的那样,-------所有日历日期都会传自己的时间进来执行它,得到ture或者false,就能知道自己这个日期时间是不是需要禁止的日期了,那么如何显示禁止和隐藏禁止呢,我觉得,这个函数传进来之后,放在一个computed里面,然后,在日历v-for渲染的时候,disable的就设置为这个computed,这样就行了
不过第二种,因为范围写的默认每次都是new Date() 所以会固定为当前时间前后一个月,看你怎么写范围了,一个月两个月三个月等等,随你
而第一种,似乎没有onpick,那为什么又可以呢
那么有个问题,同一个computed,可以根据参数返回不同的值吗
当然是可以的,一个函数你可以到处用,就好像组件一样,
如图
看了一下element的时间选择器
我想了想两点是怎么做的
一个是点击的时候如何拿到当前时间
这个倒是简单 上面的年月和下面的日
组合起来emit出来就行了,或者直接v model点了就改
一个是如何渲染得问题
首先要考虑年
年的话 获取当前年 然后前后点得时候针对这个年动态加减 就行了
然后是月 月份话只有12个 动态加减轮回渲染就行了
然后是日和星期 这两个最难搞
日有多少天 要根据平面闰年以及现在几月来决定
然后日是星期几 估计有专门的api可以算出来 调下接口就行了
然后重点来了,一般有左右两个日期选择器
如图
每个都是6行7列 毕竟7天嘛
然后左右两个板子都是做同一件事
首先计算出当前这个月有多少天
然后计算出第一天是星期几,放在相应的位置 然后算出前一个月和后一个月的日期
然后补全剩下的格子
就这样
这篇博客可以看看https://blog.csdn.net/weixin_38788347/article/details/81359673
6.elementui的table列超出隐藏tooltip悬浮显示
https://blog.csdn.net/LLL_liuhui/article/details/107814535
7.今天用一个div上面有个span,下面是个空的
但是下面部分却点击不到下下面挡住的el-tooltip,却可以点击别的元素
百思不得其解,发现原来是可以点的元素设置了.position:relative;z-index:1,设置后
于是点到了
8.今天封装公用弹框,遇到个问题
就是我传对象下去,对象里有个布尔值,控制子组件弹框的显示隐藏,但是我在父组件改变这个对象的这个布尔值,却不出现,子组件中隐藏的时候也隐藏不了。。。。
这里发现了问题所在
首先看看这篇说的https://www.cnblogs.com/1032473245jing/p/11102919.html
1.将父组件数据赋值给子组件数据,子组件间接使用,数据仅在mounted中渲染,父组件数据改变子组件数据不改变,需要用watch监听,可以深度监听
2.子组件直接使用父组件传递的数据,父组件数据改变子组件改变,不管这个对象有多少层,都能响应变化,这一点我也是多次试过的
第2种的案例
那么我这种情况应该是属于第2种,那么为什么不行呢,因为我的对象不是响应式的,没有成为data中的响应式数据
我看了一下,原来是因为我的那个对象没有定义在data中。。。。。。,真是笑死我了。。。。。这种低级错误
后来,我把对象放在data里定义了,就都可以了。。。。。。。。。。
没放之前,也就是data中都没写这个数据。。。。,可以看到就是一个普通对象
放了之后,也就是data中定义了之后,可以很明显的看到对象是响应式的了。。。。
那么我这里这种是属于典型的第2种,子组件直接使用父组件传递的数据,而不是赋值给子组件的data里的数据,这样,注意都是直接改,子组件改了传的数据,父组件也会响应,父组件改了传的数据,子组件也会响应,不论多少层,所以如果你遇到使用第1种,但是没效果,那么不要怀疑别的,就是你哪里写的不对罢了
第1种的案例
而上次我做的那个api模板里的api步骤的编辑,传了一个对象下去,那种情况,是吧传的值赋值给了子组件里的数据,那是典型的第1种,所以直接改是没效果的,因为你子组件用的数据,和你传的数据已经是两份不同的数据了,你说你改了会有用吗,会互相影响吗,是不会的,那么就需要让他们互相影响对不对,这样就和第2种的效果一样了呀,那么如何让他们能够响应式的互相影响呢,
用watch监听就行了,如果需要父组件传的那个数据改了之后能够影响子组件赋值的那个数据,那么监听父组件传的这个数据(注意对象的话要深度监听{deep:true},不然监听不到对象的变化),然后拿到newVal,也就是最新的值之后,赋值给子组件里那些被赋值的数据,它们不就响应成最新的了吗
如果需要子组件改了之后,父组件的数据也动态改变,那么监听子组件的那个被赋值的数据就好了,拿到newVal,也就是最新的值之后,赋值给父组件传过来的那个数据,
它不就更新了吗,变成了子组件更改之后的最新的数据
9.关于element的穿透样式,影响,比如弹框
关于子组件里的弹框样式,
比如我在组件a b c中都用了弹框
a b组件同级,那么他们的弹框样式不会互相影响
但是c是a的子组件
那么c的弹框就会被a的弹框样式修改影响
c自己的弹框样式修改会被覆盖
那么如何解决
我刚想到了一个好办法
那就是给dialog加类名
虽然改弹框样式不能放在组件类名里面
这样改不到
因为是全局的,和app同级,而不是在app里面
但是可以给diolog加类名呀
这样可以区分了
他妈的,搞错了一个点,之前一直以为弹框是在body里,没在id=app这个vue的div里,今天一看,居然在。。。。
这尼玛,弹框原来在app里面啊。。。。
根本没在外面
所以只用加个class名字就行了。。。。给弹框
而像这种的才不在,而是在body里, ::v-deep .el-dropdown-menu__item ,下拉框