element ui 表格组件与分页组件的二次封装

目录

效果图 

组件封装

 parseTime函数

debounce 函数

页面使用

【扩展】vue 函数式组件

函数式组件特点:

函数式组件的优点:

【扩展】vue中的render函数

一、初步认识render函数

二、为什么使用render函数

三、render函数的解析

【扩展】添加操作栏显示权限

结构改动

逻辑新增

组件引入使用 


使用组件需先下载 element ui  vue2

效果图 

组件封装

这段代码是一个封装的分页表格组件。它使用了Vue.js框架,并结合了Element UI中的el-table和el-pagination组件来实现。该组件接受一系列属性作为数据源,包括列表数据(list)、表格列(columns)、操作按钮列(operates)、总数(total)、分页参数(pagination)等。

在模板中,使用el-table组件来展示表格数据,使用el-pagination组件来实现分页功能。el-table-column用来定义每列的样式和展示内容。组件中还包括其他的一些方法和事件处理函数,如handleSizeChange用于切换每页显示的数量,handleIndexChange用于切换页码,handleSelectionChange处理多行选中等。

此外,还定义了一些样式规则来美化表格的显示效果,如设置表头颜色、调整列的样式、设置操作按钮组的布局、设置筛选弹窗和表格操作弹窗的样式等。

最后,使用了scss来编写样式表,通过设置类名来控制样式的展示。

  1. <template>标签中,定义了一个表格组件,包括表格本身,列定义,按钮操作组,和分页控件。

  2. <script>标签中,导入了必要的依赖,并定义了组件的属性(props)、数据(data)、生命周期钩子(activated、beforeDestroy、deactivated、created、mounted)和方法(methods)。

  3. props属性用于接受从父组件传递进来的数据,如数据列表 list、列定义 columns、按钮操作 operates、总数 total、分页参数 pagination 等。

  4. data数据属性包括一些内部状态,如表格高度 height、监听窗口调整大小的回调函数 $_resizeHandler、当前页码 pageIndex、表格分页信息 tableCurrentPagination、多行选中数据 multipleSelection 等。

  5. 在生命周期钩子中,组件监听窗口大小调整事件,自动调整表格高度,并在适当的生命周期中初始化和销毁事件监听器。

  6. methods包括一系列方法,如计算表头宽度的方法 headSpanFit、初始化事件监听器的方法 initListener、销毁事件监听器的方法 destroyListener、调整表格高度的方法 resize、处理每页显示数量变化的方法 handleSizeChange、处理页码变化的方法 handleIndexChange、处理多行选中的方法 handleSelectionChange 等。

  7. 最后,在<style>标签中定义了一些样式,包括表格样式、分页样式、按钮样式、筛选和操作弹窗样式等。

<!--region 封装的分页 table-->
<!--region 封装的分页 table-->
<template><div class="table"><el-table id="iTable" v-loading.iTable="options.loading" :data="list" :stripe="options.stripe" ref="mutipleTable"@selection-change="handleSelectionChange" :height="noStatic ? customHeight : height":max-height="noStatic ? customHeight : height"><!--region 选择框--><el-table-column v-if="options.mutiSelect" type="selection" style="width: 55px"></el-table-column><!--endregion--><!--region 数据列--><template v-for="(column, index) in columns"><el-table-column :min-width="headSpanFit(column)" :prop="column.prop" :label="column.label" :align="column.align":width="column.width"><template slot-scope="scope"><template v-if="!column.render"><template v-if="column.formatter"><span v-html="column.formatter(scope.row, column)"></span></template><template v-else><span>{{ scope.row[column.prop] === 0? 0: scope.row[column.prop] || "--" }}</span></template></template><template v-else><expand-dom :column="column" :row="scope.row" :render="column.render" :index="index"></expand-dom></template></template></el-table-column></template><!--endregion--><!--region 按钮操作组--><el-table-column ref="fixedColumn" label="操作" align="center" :width="operates.width" :fixed="operates.fixed"v-if="operates.list.length > 0"><template slot-scope="scope"><div class="operate-group"><template v-for="(btn, key) in operates.list"><div class="item" v-if="typeof btn.show == 'function'? btn.show(scope.$index, scope.row): btn.show"><el-button :type="btn.type" :key="key + 'itbtn'" :size="btn.size || 'mini'" :icon="btn.icon" :disabled="typeof btn.disabled == 'function'? btn.disabled(scope.$index, scope.row): btn.disabled" :plain="btn.plain" @click.native.prevent="btn.method(scope.$index, scope.row)">{{btn.label }}</el-button></div></template></div></template></el-table-column><!--endregion--></el-table><div style="height: 12px"></div><!--region 分页--><el-pagination v-if="pagination" @size-change="handleSizeChange" @current-change="handleIndexChange":page-size="tableCurrentPagination.pageSize" :page-sizes="this.tableCurrentPagination.pageArray":current-page="tableCurrentPagination.pageIndex" layout="total,sizes, prev, pager, next,jumper":total="total"></el-pagination><!--endregion--></div>
</template>
<!--endregion-->
<script>
import { debounce } from "@/utils";
const _pageArray = [20, 50, 100]; // 每页展示条数的控制集合
export default {props: {list: {type: Array,default: [], // prop:表头绑定的地段,label:表头名称,align:每列数据展示形式(left, center, right),width:列宽}, // 数据列表columns: {type: Array,default: [], // 需要展示的列 === prop:列数据对应的属性,label:列名,align:对齐方式,width:列宽},operates: {type: Object,default: {}, // width:按钮列宽,fixed:是否固定(left,right),按钮集合 === label: 文本,type :类型(primary / success / warning / danger / info / text),show:是否显示,icon:按钮图标,plain:是否朴素按钮,disabled:是否禁用,method:回调方法},total: {type: Number,default: 0,}, // 总数pagination: {type: Object,default: null, // 分页参数 === pageSize:每页展示的条数,pageIndex:当前页,pageArray: 每页展示条数的控制集合,默认 _page_array},noStatic: false, // 是否计算表格高度customHeight: {//与noStatic一起使用type: Number,default: 320,},otherHeight: {type: Number,default: 180,}, // 计算表格的高度options: {type: Object,default: {stripe: false, // 是否为斑马纹 tableloading: false, // 是否添加表格loading加载动画highlightCurrentRow: false, // 是否支持当前行高亮显示mutiSelect: false, // 是否支持列表项选中功能},}, // table 表格的控制参数},components: {expandDom: {functional: true,props: {row: Object,render: Function,index: Number,column: {type: Object,default: null,},},render: (h, ctx) => {const params = {row: ctx.props.row,index: ctx.props.index,};if (ctx.props.column) params.column = ctx.props.column;return ctx.props.render(h, params);},},},data() {return {height: 250,$_resizeHandler: null,pageIndex: 1,tableCurrentPagination: {},multipleSelection: [], // 多行选中};},activated() {// 通常是在使用 Vue.js 的 <keep-alive> 包装时,组件会被缓存并在重新激活时调用这个钩子函数。if (!this.$_resizeHandler) {// avoid duplication initthis.initListener();}// when keep-alive chart activated, auto resizethis.resize();},//当组件即将被销毁(beforeDestroy)时,会调用这个钩子函数。beforeDestroy() {this.destroyListener();},//当组件被停用(deactivated),通常也是在 <keep-alive> 包装下,组件会调用这个钩子函数。deactivated() {this.destroyListener();},created() { },mounted() {this.initListener();if (this.pagination && !this.pagination.pageSizes) {this.pagination.pageArray = _pageArray; // 每页展示条数控制}this.tableCurrentPagination = this.pagination || {pageSize: this.total,pageIndex: 1,}; // 判断是否需要分页},methods: {//计算小列宽headSpanFit(column) {let labelLong = column.label.length; // 表头label长度let size = 20; // 根据需要定义标尺,直接使用字体大小确定就行,也可以根据需要定义let minWidth = labelLong * size < 100 ? 100 : labelLong * size; // 根据label长度计算该表头最终宽度return minWidth;},// 初始化监听器的方法。initListener() {this.$_resizeHandler = debounce(() => {this.resize();}, 200);window.addEventListener("resize", this.$_resizeHandler);this.$nextTick(() => {this.resize();});},//这是一个销毁监听器的方法。destroyListener() {window.removeEventListener("resize", this.$_resizeHandler);this.$_resizeHandler = null;},//计算表格的高度resize() {// 不需要计算if (this.noStatic) {return;}const { mutipleTable } = this.$refs;// 窗口的高度减去表格的顶部偏移let staticHeight =window.innerHeight - this.$refs.mutipleTable.$el.offsetTop - this.otherHeight;this.height = staticHeight < 250 ? 250 : staticHeight;console.log(this.height);//保表格的布局在高度调整后得以更新。mutipleTable && mutipleTable.doLayout();},// 切换每页显示的数量handleSizeChange(size) {if (this.pagination) {this.tableCurrentPagination = {pageIndex: 1,pageSize: size,};this.$emit("handleSizeChange", this.tableCurrentPagination);}},// 切换页码handleIndexChange(currnet) {if (this.pagination) {this.tableCurrentPagination.pageIndex = currnet;this.$emit("handleIndexChange", this.tableCurrentPagination);}},// 多行选中handleSelectionChange(val) {this.multipleSelection = val;this.$emit("handleSelectionChange", val);},// 显示 表格操作弹窗showActionTableDialog() {this.$emit("handelAction");},},
};
</script><style lang="scss">
.table {height: 100%;.el-pagination {float: right;margin: 20px;}.el-table__header-wrapper,.el-table__fixed-header-wrapper {thead {tr {th {color: #333333;}}}}.el-table-column--selection .cell {padding: 0;text-align: center;}.el-table__fixed-right {bottom: 0 !important;right: 6px !important;z-index: 1004;}.operate-group {display: flex;flex-wrap: wrap;.item {margin-top: 4px;margin-bottom: 4px;display: block;flex: 0 0 50%;}}.filter-data {top: e("calc((100% - 100px) / 3)");background-color: rgba(0, 0, 0, 0.7);}.table-action {top: e("calc((100% - 100px) / 2)");background-color: rgba(0, 0, 0, 0.7);}.fix-right {position: absolute;right: 0;height: 100px;color: #ffffff;width: 30px;display: block;z-index: 1005;writing-mode: vertical-rl;text-align: center;line-height: 28px;border-bottom-left-radius: 6px;border-top-left-radius: 6px;cursor: pointer;}
}
</style>

 parseTime函数

// 日期格式化
export function parseTime(time, pattern) {if (arguments.length === 0 || !time) {return null}const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'let dateif (typeof time === 'object') {date = time} else {if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {time = parseInt(time)} else if (typeof time === 'string') {time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');}if ((typeof time === 'number') && (time.toString().length === 10)) {time = time * 1000}date = new Date(time)}const formatObj = {y: date.getFullYear(),m: date.getMonth() + 1,d: date.getDate(),h: date.getHours(),i: date.getMinutes(),s: date.getSeconds(),a: date.getDay()}const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {let value = formatObj[key]// Note: getDay() returns 0 on Sundayif (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }if (result.length > 0 && value < 10) {value = '0' + value}return value || 0})return time_str
}

debounce 函数

export function debounce(func, wait, immediate) {let timeout, args, context, timestamp, resultconst later = function() {// 据上一次触发时间间隔const last = +new Date() - timestamp// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 waitif (last < wait && last > 0) {timeout = setTimeout(later, wait - last)} else {timeout = null// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用if (!immediate) {result = func.apply(context, args)if (!timeout) context = args = null}}}return function(...args) {context = thistimestamp = +new Date()const callNow = immediate && !timeout// 如果延时不存在,重新设定延时if (!timeout) timeout = setTimeout(later, wait)if (callNow) {result = func.apply(context, args)context = args = null}return result}
}

页面使用

<template><div class="table-page"><!--region table 表格--><app-table :list="list" :total="total" :otherHeight="otherHeight" :options="options" :pagination="pagination":columns="columns" :operates="operates" @handleSizeChange="handleSizeChange" @handleIndexChange="handleIndexChange"@handleSelectionChange="handleSelectionChange"></app-table><!--endregion--></div>
</template>
<script>
import {parseTime,} from "@/utils/ruoyi";
export default {data() {return {total: 0,list: [{id: 1,title: '标题',state: 0,author: '张三',phone: '12346788901',email: '1234556778@qq.com',createDate: "2023-04-23 16:11:38"}],otherHeight: 208,columns: [{prop: 'id',label: '编号',align: 'center',width: 60},{prop: 'title',label: '标题',align: 'center',width: 400,formatter: (row, column, cellValue) => {return `<span style="white-space: nowrap;color: dodgerblue;">${row.title}</span>`}},{prop: 'state',label: '状态',align: 'center',width: '160',render: (h, params) => {return h('el-tag', {props: { type: params.row.state === 0 ? 'success' : params.row.state === 1 ? 'info' : 'danger' } // 组件的props}, params.row.state === 0 ? '上架' : params.row.state === 1 ? '下架' : '审核中')}},{prop: 'author',label: '作者',align: 'center',width: 120},{prop: 'phone',label: '联系方式',align: 'center',width: 160},{prop: 'email',label: '邮箱',align: 'center',width: 240},{prop: 'createDate',label: '发布时间',align: 'center',width: 180,formatter: (row, column, cellValue) => {return parseTime(row.createDate)}}], // 需要展示的列operates: {width: 200,fixed: 'right',list: [{label: '编辑',type: 'warning',show: (index, row) => {return true},icon: 'el-icon-edit',plain: true,disabled: false,method: (index, row) => {this.handleEdit(index, row)}},{label: '删除',type: 'danger',icon: 'el-icon-delete',show: true,plain: false,disabled: (index, row) => {return false},method: (index, row) => {this.handleDel(index, row)}}]}, // 操作按钮组pagination: {pageIndex: 1,pageSize: 20}, // 分页参数options: {stripe: true, // 是否为斑马纹 tableloading: false, // 是否添加表格loading加载动画highlightCurrentRow: true, // 是否支持当前行高亮显示mutiSelect: true // 是否支持列表项选中功能} // table 的参数}},components: {expandDom: {props: {column: {required: true},row: {required: true}},render(h) {return h('div', {}, ([this.column.render(this.row, this.column)]))}}},mounted() {},methods: {// 切换每页显示的数量handleSizeChange(pagination) {this.pagination = pagination},// 切换页码handleIndexChange(pagination) {this.pagination = pagination},// 选中行handleSelectionChange(val) {console.log('val:', val)},// 编辑handleEdit(index, row) {console.log(' index:', index)console.log(' row:', row)},// 删除handleDel(index, row) {console.log(' index:', index)console.log(' row:', row)},}
}
</script>

【扩展】vue 函数式组件

函数式组件特点:

  • 没有管理任何状态
  • 没有监听任何传递给它的状态
  • 没有生命周期方法
  • 它只是接收一些prop的函

我们将这样的组件标记为functional

  • 无状态 == 无响应式数据
  • 无实例 == 无this上下文

函数式组件的优点:

  • 渲染开销低,因为函数式组件只是函数;
 {functional: true,// Props 是可选的props: {// ...},// 为了弥补缺少的实例// 提供第二个参数作为上下文render: function (createElement, context) {// ...}
}

props: 提供所有prop的对象
children:VNode 子节点的数组
slots: 一个函数,返回了包含所有插槽的对象
scoptedSlots:(2.6.0) 一个暴露传入的作用域插槽的对象,也以函数形式暴露普通插槽
data:传递个组件的整个数据对象,作为createElement的第二个参数传入组件
parent:对父组件的引用
listeners:(2.3.0+) 一个包含了:所有父组件为当前组件祖册的事件监听器对象,是data.on的一个别名
injections:(2.3.0+) 如果使用了inject选项,则改对象包含了:应当被注入的属性;

【扩展】vue中的render函数

一、初步认识render函数

import Vue from 'vue'
import App from './App'Vue.config.productionTip = falsenew Vue({el: '#app',render: h => h(App)
})

在使用脚手架创建vue项目的过程,我们很容易看到render这个函数,相对于其他标签,我们对于render还是比较陌生的,因此写下这篇文章你我共同理解。

二、为什么使用render函数


VUE推荐在绝大多数情况下使用template来创建我们的HTML。然而在一些场景中,我们真的需要JavaScript的完全编程的能力,这就是render函数,它比template更接近编译器。(这是官方的话)
简单来说,我们为什么要使用render函数呢?? 便是因为我们最经常使用的一个引入。

import Vue from "vue";

这一个引入你看似没有任何问题,但问题恰恰就是出在这。在不同版本的vue中,有vue.js和vue.runtime.xxx.js这两种js文件。其中

(1)vue.js是完整版的vue,包含核心功能+模板解析器。

(2)vue.runtime.xxx.js是运行版vue,只包含核心功能,没有模板解析器。

VUE开发者为了让我们打包的文件能尽可能小一点,在上述引入的是运行版vue。因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,这时候就需要使用render函数去接收到的createElement函数去指定具体内容,创建html模板。

三、render函数的解析


render 函数即渲染函数,它是个函数,它的参数 createElement 也是个函数。

上边的代码中 render: h => h(App) ,这是 ES6的箭头函数的写法,可以把 h 当作 createElement 的别名。所以这段代码其实相当于

render: function (createElement) {return createElement(App)
}

这个函数的作用就是生成一个 VNode节点,render 函数得到这个 VNode 节点之后,返回给 Vue.js 的 mount 函数,渲染成真实 DOM 节点,并挂载到根节点上。

createElement 函数的返回值是 VNode(即:虚拟节点)

createElement 函数的3个参数

  • 一个 HTML 标签字符串,组件选项对象,或者解析上述任何一种的一个 async 异步函数。类型:String | Object | Function。必需。
  • 一个包含模板相关属性的数据对象,你可以在 template 中使用这些特性。类型:Object。可选。
  • 子虚拟节点 (VNodes),由 createElement() 构建而成,也可以使用字符串来生成“文本虚拟节点”。类型:String | Array。可选
new Vue({el: '#app',render:function (createElement) {//1.普通用法// createElement(标签,{属性},[内容])return createElement("h2",{class:"box"},['hello',createElement("button",["按钮"])])}
})

同时createElement也可以传进去一个组件,因此 

render: h => h(App)

等同于 

render:function (createElement) {return createElement(App)}

【扩展】添加操作栏显示权限

结构改动

通过函数式组件渲染 操作按钮部分

    <el-table-columnref="fixedColumn"label="操作"align="center":width="operates.width":fixed="operates.fixed"v-if="operates.list.length > 0"><template slot-scope="scope"><expand-dom:row="scope.row":render="renderOperates":index="scope.$index"></expand-dom></template></el-table-column>

逻辑新增

这段代码是一个Vue.js组件方法,用于渲染操作按钮。让我逐步解释代码的主要部分:

1. `renderOperates` 方法:这是一个渲染操作按钮的方法。它接受两个参数 `h` 和 `params`,其中 `h` 是Vue的createElement函数,用于创建虚拟DOM,而 `params` 包含一些参数数据。

2. `const endArr = this.rebuildList(params);`:这一行调用了 `rebuildList` 方法,它会根据权限验证后的结果生成最终的按钮数组,然后将这个数组存储在 `endArr` 变量中。

3. `let outSideBtnArr = endArr.slice(0, 2);` 和 `let insideArr = endArr.slice(2);`:这两行将 `endArr` 分为两个部分,前两个按钮存储在 `outSideBtnArr` 中,其余的按钮存储在 `insideArr` 中。

4. `const buttonArr = [];`:创建一个空数组 `buttonArr`,用于存储最终要渲染的按钮。

5. `outSideBtnArr.forEach((item) => { ... });`:这是一个循环遍历 `outSideBtnArr` 的循环,对每个按钮调用 `renderOutsideButton` 方法进行渲染,然后将渲染结果添加到 `buttonArr` 中。

6. `if (insideArr.length > 0) { ... }`:这是一个条件判断,如果 `insideArr` 中有按钮,则调用 `renderDropdownButton` 方法进行渲染,然后将渲染结果添加到 `buttonArr` 中。

7. 最后,使用 `h("div", { attrs: { class: "operate-group" } }, buttonArr)` 创建一个 `<div>` 元素,设置其类名为 "operate-group",并将 `buttonArr` 中的按钮渲染到这个 `<div>` 元素中,最终返回这个 `<div>` 元素的虚拟DOM。

接下来,代码中还包含了两个方法 `renderOutsideButton` 和 `renderDropdownButton`,它们分别用于渲染外部按钮和下拉按钮。这两个方法的主要作用是创建相应的按钮元素,并设置按钮的属性、样式和点击事件处理函数。

最后,代码中还包括一个 `rebuildList` 方法,用于根据权限验证结果来生成最终的按钮数组。它会遍历操作按钮列表,根据按钮的显示权限和角色身份权限来判断是否允许显示该按钮,然后返回允许显示的按钮数组。

总的来说,这段代码用于动态生成操作按钮组件,根据权限和角色身份权限来控制按钮的显示和行为。

    // 用于渲染操作按钮的方法renderOperates(h, params) {const endArr = this.rebuildList(params); //权限验证后最终按钮数组let outSideBtnArr = endArr.slice(0, 2); //外部按钮 默认前两个let insideArr = endArr.slice(2); //下拉菜单按钮数组const buttonArr = []; //最终渲染数组outSideBtnArr.forEach((item) => {buttonArr.push(this.renderOutsideButton(h, item, params));});if (insideArr.length > 0) {buttonArr.push(this.renderDropdownButton(h, insideArr, params));}return h("div", { attrs: { class: "operate-group" } }, buttonArr);},// 渲染外部按钮renderOutsideButton(h, item, params) {return h("el-button",{// 组件的属性(数据)props: {type: item.type || "text", //类型(primary / success / warning / danger / info / text)icon: item.icon || "", //icon:按钮图标plain: item.plain || false, //plain:是否朴素按钮size: item.size || "mini", //大小},// 组件的属性(html属性)attrs: {title: item.label, //label: 文本},// 样式style: {color: item.label == "删除" ? "#ff4057" : "",},// 按钮的点击事件处理函数on: {click: () => {item.method(params.index, params.row);},},},item.label //label: 文本);},// 渲染下拉按钮renderDropdownButton(h, insideArr, params) {return h(// 创建了一个 "el-dropdown" 组件"el-dropdown",// dropdown 样式{class: ["custom-dropdown"],// 组件的属性(数据):props: {trigger: "click", //下拉框点击触发},},[// "el-dropdown" 组件中的buttonh("el-button",{// 按钮样式style: {fontSize: "18px",},// 按钮类名class: ["custom-text"],props: {type: "text",plain: false,size: "mini",},},// 在按钮的内容中,使用了一个 "i" 标签,其 class 属性为 "el-icon-more",显示一个图标。[h("i", { class: "el-icon-more" })]),// 创建了一个 "el-dropdown-menu" 组件h("el-dropdown-menu",// 传入slot{slot: "dropdown",},// 对传入的按钮循环渲染出el-dropdown-item"insideArr.map((item) => {return h("el-dropdown-item",{nativeOn: {click: () => {item.method(params.index, params.row);},},},item.label);})),]);},// 校验权限rebuildList({ row }) {// 验证是否显示权限和角色身份权限return this.operates.list.filter((item) => {if (typeof item.show === "function") {return item.show(row);} else if (typeof item.show === "boolean" && item.show) {return true;}// 如果没有显示权限要求,则继续验证角色身份权限if (item.haspermission) {return checkPermi(item.haspermission);}// 如果没有角色身份权限要求,则默认允许显示return true;});},

组件引入使用 

只需添加按钮对应的权限标识符字段即可

      operates: {fixed: "right",list: [{label: "编辑",type: "text",haspermission: ["agent:del"],icon: "el-icon-edit",plain: false,disabled: false,method: (index, row) => {this.handleEdit(index, row);},},{label: "删除",show: true,plain: false,disabled: (index, row) => {return false;},method: (index, row) => {this.handleDel(index, row);},},],}, // 操作按钮组

本文用的是若依框架 上文中添加权限部分 checkPermi 函数 为若伊提供的校验按钮权限方法(组件引入haspermission字段同理 可以根据业务场景自行修改,传入haspermission权限标识符即可)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/71305.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDFS文件删除后,HIVE元数据还存在的问题

一.背景 手动在hdfs上删除了一个表的分区数据(inc_day2023-08-30)&#xff0c;当查询这个表这个分区的数据时报错文件不存在 二.原因 即HDFS数据删除了&#xff0c;但是hive metastore元数据却没有更新&#xff0c;使用show partitions tablename 发现该分区还存在 三.解决办法…

【 Tkinter界面-练习04】 画板作画详细揭示

一、说明 对画布的掌握分三个部分&#xff0c;将图形paint到画布、动画move、鼠标画&#xff1b;本篇将侧重于鼠标画的功能&#xff0c;提起鼠标画实现&#xff0c;将涉及一系列组合操作才能完成&#xff0c;这里将一一加以介绍。 Canvas 小部件具有大量功能&#xff0c;我们不…

C++提高篇:深入理解纯虚函数和抽象类

在C中&#xff0c;纯虚函数和抽象类是面向对象编程中重要的概念。本文将会深入探讨这两个概念的含义、如何定义和使用它们&#xff0c;以及它们在实际开发中的应用。 一、什么是纯虚函数&#xff1f; 在C中&#xff0c;纯虚函数是指在基类中声明但没有实现的虚函数。纯虚函数的…

2023全国大学生数学建模ABCDE选题建议,思路模型,小白要怎么选?难度怎么样

首先最重要的&#xff0c;难度C<B<A&#xff0c;D、E题推荐选E题 大家可以查看我们的视频讲解&#xff0c;在这里&#xff1a;【2023全国大学生数学建模竞赛选题建议&#xff0c;难度分析&#xff0c;小白应该怎么选】 https://b23.tv/S6O26uc 选题建议视频播放​b23.t…

设备管理系统有什么功能?它有什么用?

设备管理系统已成为现代化大规模研究所&#xff0c;信息化管理体系建设中最为关键的要素。随着工业设备的机械化、自动化、大型化、高速化以及复杂化等因素不断叠加&#xff0c;设备设施对于工业生产的作用和影响越来越大&#xff0c;其各项制度和流程也涉及面广、内容繁杂。  …

私有化部署即时通讯平台,完美替代飞书和钉钉的SaaS系统

在当今快速发展的数字化时代&#xff0c;企业对于安全、灵活、可定制的即时通讯平台需求不断增长。作为一家领先的品牌&#xff0c;WorkPlus专注于提供私有化部署的即时通讯平台&#xff0c;完美替代飞书和钉钉的SaaS系统。本文将重点介绍WorkPlus如何通过创新的解决方案&#…

系统学习Linux-PXE无人值守装机(附改密)

目录 pxe实现系统自动安装pxe工作原理 大致的工作过程如下&#xff1a; PXE的组件&#xff1a; 一、配置vsftpd 二、配置tftp 三、准备pxelinx.0文件、引导文件、内核文件 四、配置dhcp 配置ip 配置dhcp 五、创建default文件 六、新建测试主机用来测试装机效果 七、…

2023 年高教社杯全国大学生数学建模竞赛-E 题 黄河水沙监测数据分析详解+思路+Python代码

2023 年高教社杯全国大学生数学建模竞赛-E 题 黄河水沙监测数据分析 十分激动啊啊啊题目终于出来了&#xff01;&#xff01;官网6点就进去了结果直接卡死现在才拿到题目&#xff0c;我是打算A-E题全部做一遍。简单介绍一下我自己&#xff1a;博主专注建模四年&#xff0c;参与…

STC单片机+EC11编码器实现调节PWM输出占空比

STC单片机+EC11编码器实现调节PWM输出占空比 📌相关篇《stc单片机外部中断+EC11编码器实现计数功能》 📍《STC15单片机特有的PWM寄存器和普通定时器实现PWM输出》 🎬效果演示: 🌼 通过逻辑分析仪获取P11引脚上的信号波形,查看其对应输出的占空比。 ✨本例程基于上面两…

复制粘贴是怎么实现的

在上面的代码中&#xff0c;command 和 select 是自定义的函数。它们的作用如下&#xff1a; 实现复制粘贴的思路&#xff1a; 创建一个 textarea 标签将 textarea 移出可视区域给这个 textarea 赋值将这个 textarea 标签添加到页面中调用 textarea 的 select 方法调用 docum…

(c++)类和对象 上篇

目录 1.面向过程和面向对象初步认识 2.类的引入 3.类的定义 4.类的访问限定符及封装 5.类的作用域 6.类的实例化 7.类的对象大小的计算 8.类成员函数的this指针 1.面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步…

外滩大会今日开幕 近20位“两院”院士、诺贝尔奖和图灵奖得主齐聚

2023 Inclusion外滩大会9月7日在上海黄浦世博园正式开幕。这场以“科技创造可持续未来”为主题的大会为期三天&#xff0c;近20位“两院”院士、诺贝尔奖和图灵奖得主&#xff0c;全球超500位有影响力的科技领军企业和专家学者&#xff0c;将在此带来一场科技、人文和产业的思想…

Linux下go环境安装、环境配置并执行第一个go程序

一、安装 1.Golang对Linux的内核版本要求 GO对Linux内核版本最低要求是 2.6.23&#xff0c;对应要求操作系统版本是&#xff1a; RHEL 6.0CentOS 6.0即&#xff0c;不支持 (RHEL 和 CentOS) 的 (4.x or 5.x)。2.下载golang的代码版本 Golang的官网下载地址&#xff1a;https:…

Vue2+Vue3基础入门到实战项目(七)——智慧商城项目

Vue 核心技术与实战 智慧商城 接口文档&#xff1a;https://apifox.com/apidoc/shared-12ab6b18-adc2-444c-ad11-0e60f5693f66/doc-2221080 演示地址&#xff1a;http://cba.itlike.com/public/mweb/#/ 01. 项目功能演示 1.明确功能模块 启动准备好的代码&#xff0c;演示…

Unity 之 利用数组来管理资源

文章目录 在Unity中&#xff0c;资源数组&#xff08;Resource Arrays&#xff09;不是Unity的标准概念。然而&#xff0c;您可能在特定上下文中使用数组来管理资源或游戏对象。我将解释如何在Unity中使用数组来管理资源。 资源管理&#xff1a; 在Unity中&#xff0c;资源通常…

React Hook之useContext

1. 什么是useContext React官方解释&#xff1a;useContext 是一个 React Hook&#xff0c;可以让你读取和订阅组件中的 context&#xff08;React官方文档地址&#xff09;。 通俗的讲&#xff0c;useContext的作用就是&#xff1a;实现组件间的状态共享&#xff0c;主要应用场…

2023 年全国大学生数学建模A题目-定日镜场的优化设计

A题目是个典型的优化问题 大致思路&#xff08;非完整&#xff09; 先说题目的模型&#xff0c;有点类似一个人拿着镜子&#xff0c;这个镜子最终要映射到某个点上&#xff0c;有点类似下面这个玩意儿&#xff0c;只不过是个大型的而已 规划的吸收塔类似这个烧水壶&#xff0c;…

无涯教程-JavaScript - ERFC.PRECISE函数

描述 ERFC.PRECISE函数返回x和无穷大之间集成的互补ERF函数。 互补误差函数等于1-ERF(即1-误差函数),由等式给出- $$Erfc(x) \frac {2} {\sqrt {\pi}} \int_ {x} ^ {\infty} e ^ {-t ^ 2} dt $$ 语法 ERFC.PRECISE(x)争论 Argument描述Required/OptionalxThe lower bound…

对象临时中间状态的条件竞争覆盖

Portswigger练兵场之条件竞争 &#x1f984;条件竞争之对象临时中间状态的条件竞争 Lab: Partial construction race conditions&#x1f680;实验前置必要知识点 某些框架尝试通过使用某种形式的请求锁定来防止意外的数据损坏。例如&#xff0c;PHP 的本机会话处理程序模块…

IT运维监控系统和网络运维一样吗

IT运维监控系统和网络运维不是一样的。IT运维监控系统是一系列IT管理产品的统称&#xff0c;它所包含的产品功能强大、易于使用、解决方案齐全&#xff0c;可一站式满足用户的各种IT管理需求。而网络运维是指对网络设备进行监控、维护和管理&#xff0c;包括硬件故障的排除、软…