1、列表实现
<el-table :data="tableData" border style="width: 100%" @selection-change="handleSelectionChange" :header-cell-style="{'text-align':'center'}">
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="date" label="日期" align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="left">
</el-table-column>
<el-table-column prop="age" label="年龄" align="right">
</el-table-column>
<el-table-column prop="sex" label="性别" align="left" :formatter="sexFormat">
</el-table-column>
<el-table-column prop="phone" label="电话" align="left">
</el-table-column>
<el-table-column prop="address" label="地址" :show-overflow-tooltip="true" align="left">
</el-table-column>
<el-table-column prop="enableFlag" label="启用状态" :formatter="enableFlagFormat" align="left">
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template #default="scope">
<el-button size="mini" type="text" @click="handleSelect(scope.$index,scope.row)">详情</el-button>
<el-button size="mini" type="text" @click="handleUpdate(scope.$index,scope.row)">修改</el-button>
</template>
</el-table-column>
</el-table>
vue3 中无法使用slot-scope的问题
vue2:上下对应,title是自己随便起的名字
<div slot="title"></div>
<div slot="title" slot-scope="scope"></div>
vue3:上下对应,title是自己随便起的名字
1、注意,vue3中只能用template, # 等同于 slot=
<template #title></template>
2、注意,vue3中只能用template, # 等同于 slot=
<template #title="scope"></template>
2、el-dialog实现
<el-dialog v-model="addOpen" class="diaStyle" style="height: 80vh; overflow-y: auto" :title="title">
<el-form ref="ruleForm" :model="form" :inline="true" :rules="rules" label-width="80px" style="margin-bottom: 20px">
<el-row>
<el-col :span="12">
<el-form-item label="日期" prop="date" style="width: 100%;">
<el-input v-model="form.date" type="text" placeholder="请输入日期" :disabled="disabled" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名" prop="name" style="width: 100%;">
<el-input v-model="form.name" type="text" placeholder="请输入姓名" :disabled="disabled" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="性别" prop="sex" style="width: 100%;">
<el-select v-model="form.sex" placeholder="请选择性别" :disabled="disabled">
<el-option v-for="item in sexOption" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="年龄" prop="age" style="width: 100%;">
<el-input v-model="form.age" type="text" placeholder="请输入年龄" :disabled="disabled" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="联系方式" prop="phone" style="width: 100%;">
<el-input v-model="form.phone" type="text" placeholder="请输入联系方式" :disabled="disabled" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="启用状态" prop="enableFlag" style="width: 100%;">
<el-radio-group v-model="form.enableFlag" :disabled="disabled">
<el-radio v-for="dict in enableOption" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="地址" prop="address" style="width: 100%;">
<el-input v-model="form.address" type="text" placeholder="请输入地址" :disabled="disabled" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm" v-preventReClick="2000" v-if="confDisabled">保 存</el-button>
<el-button @click="closeDialog">{{buttonName}}</el-button>
</div>
</el-dialog>
2.1、vue3 中无法使用:visible.sync的问题
:visible指的是属性绑定,表示弹框的显示隐藏。当:visible的值为ture的时候,弹框显示,当为false的时候,弹框隐藏。:visible.sync指的就是同步动态双向的来表示visible的值。
在vue3中取而代之的是v-model,将:visible.sync 改为 v-model
2.2、submitForm提交校验form表单
<script setup>
import { toRefs, ref, reactive, unref} from 'vue'
/** 提交按钮 */
let submitForm = () => {
const ff = unref(ruleForm);
if (!ff) return;
ruleForm.value.validate((valid) => {
if (valid) {
if (form.value.id != undefined) {
instance.proxy.$message({
message: 'id为:' + form.value.id + '的数据修改成功',
type: 'success',
})
addOpen.value = false;
reset();
} else {
instance.proxy.$message({
message: '新增成功',
type: 'success',
})
addOpen.value = false;
reset();
}
}
});
</script>
3、分页实现
<el-pagination class="v3-page" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage4"
:page-sizes="[5,10, 20, 30, 40]" :page-size="5" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
<script setup>
import { toRefs, ref, reactive} from 'vue'
const handleSizeChange = (val) => {
console.log(`每页 ${val} 条`);
pageSize.value = val
getListData();
}
const handleCurrentChange = () => {
console.log(`当前页: ${val}`);
page.value = val
getListData();
}
</script>
vue3 Element-UI 插件 Pagination 显示为英文问题
在mains.js 里添加
import ElementPlus from 'element-plus'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
// en是英文 zh-cn 是中文
app.use(ElementPlus, {
locale: zhCn,
})
4、$message提示消息
<script setup>
import { getCurrentInstance } from 'vue'
import { getTenantDatas } from '@/api/v3'
//使用message
const instance = getCurrentInstance()
const { proxy } = getCurrentInstance();
instance.proxy.$message({
message: `操作成功`,
type: 'success',
})
</script>
5、监听
5.1普通监听
<script setup>
import { toRefs, ref, reactive, watch} from 'vue'
const count = ref(0)
watch(count, (newValue, oldValue) => {
if (newValue) {
instance.proxy.$message({
message: `我侦听到了count状态的变化,当前值为${newValue},从而处理相关逻辑`,
type: 'success',
})
}
})
</script>
5.2深度监听
<script setup>
import { toRefs, ref, reactive, watch} from 'vue'
const user = reactive({
name: 'zs',
age: 18,
})
//深度监听
watch(
user,
(value) => {
console.log(value)
instance.proxy.$message({
message: `我侦听到了user年龄的变化,当前值为${value.age},从而处理相关逻辑`,
type: 'success',
})
},
{
// 深度监听,,,当ref的值是一个复杂数据类型,需要深度监听
deep: true,
immediate: true
}
)
</script>
6、onMounted钩子函数
<script setup>
import { toRefs, ref, reactive, onMounted} from 'vue'
//注册周期钩子:钩子可以用来在组件完成初始渲染并创建 DOM 节点后运行代码
onMounted(() => {
instance.proxy.$message({
message: "生命周期函数:onMounted",
type: 'success',
})
})
</script>
7、reactive 和 ref区别
1、reactive 和 ref 是 Vue 3 中的两种响应式数据绑定方式,ref 适用于简单的响应式数据,而 reactive 则适用于复杂对象或数组的响应式数据。
2、ref:使用 .value 属性来访问和修改值。
3、reactive:可以直接访问和修改对象或数组的属性或元素,而无需使用 .value。
8、父子组件相互调用
1、父组件
<template>
<div id="example1" class="demo">
<child ref="childRef" :parentData="state" :parentFunction="myFunction" style="margin-top: 20px;" />
</div>
</template>
<script setup>
import { toRefs, ref, reactive, watch, unref, computed, onMounted } from 'vue'
import child from './views/child.vue'
import { getCurrentInstance } from 'vue'
const state = reactive({
patientInfo: null,
ActiveIndex: 0,
myData: '我是父组件里的属性',
name: '孩子',
age: '15',
sex: '男',
})
const myFunction = (item) => {
instance.proxy.$message({
message: '我是父组件里的方法',
type: 'success',
})
}
//调用子组件中的方法
const childRef = ref(null);
let handleChild = () => {
childRef.value.changeData();
}
2、子组件
<template>
<div id="example1" class="demo" style="border: 1px solid blue">
<el-form :model="dataForm" label-width="80px" style="margin-bottom: 20px">
<el-row>
<el-col :span="12">
<el-form-item label="解释" prop="myData" style="width: 100%;">
<el-input v-model="dataForm.myData" type="text" placeholder="请输入解释" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名" prop="name" style="width: 100%;">
<el-input v-model="dataForm.name" type="text" placeholder="请输入姓名" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="性别" prop="sex" style="width: 100%;">
<el-input v-model="dataForm.sex" type="text" placeholder="请输入性别" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="年龄" prop="age" style="width: 100%;">
<el-input v-model="dataForm.age" type="text" placeholder="请输入年龄" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-button size="mini" type="primary" @click="handleClick()">触发</el-button>
</div>
</template>
<script setup>
import { toRefs, ref, reactive, watch, unref, defineExpose, computed } from 'vue'
import { getCurrentInstance } from 'vue'
//使用message
const instance = getCurrentInstance()
const { proxy } = getCurrentInstance();
const props = defineProps({
parentData: {
type: Object,
default: () => {
return {}
}
},
parentFunction: {
type: Function,
default: () => null,
},
})
//计算属性computed函数
const dataForm = computed(() => props.parentData);
let handleClick = () => {
//父组件中的方法
props.parentFunction(dataForm);
}
//子组件定义方法供父组件调用
const changeData = () => {
instance.proxy.$message({
message: '我是子组件里的方法',
type: 'success',
})
}
defineExpose({
changeData,
});
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
3、效果
9、完整demo代码
9.1、app.vue
<template>
<div id="example1" class="demo">
<el-row :gutter="10" style="margin-bottom: 10px">
<el-col :span="1.5">
<el-button type="primary" size="mini" @click="handleInsert">
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="primary" size="mini" @click="handleChild">
子组件调用
</el-button>
</el-col>
</el-row>
<el-table :data="tableData" border style="width: 100%" @selection-change="handleSelectionChange" :header-cell-style="{'text-align':'center'}">
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="date" label="日期" align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="left">
</el-table-column>
<el-table-column prop="age" label="年龄" align="right">
</el-table-column>
<el-table-column prop="sex" label="性别" align="left" :formatter="sexFormat">
</el-table-column>
<el-table-column prop="phone" label="电话" align="left">
</el-table-column>
<el-table-column prop="address" label="地址" :show-overflow-tooltip="true" align="left">
</el-table-column>
<el-table-column prop="enableFlag" label="启用状态" :formatter="enableFlagFormat" align="left">
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template #default="scope">
<el-button size="mini" type="text" @click="handleSelect(scope.$index,scope.row)">详情</el-button>
<el-button size="mini" type="text" @click="handleUpdate(scope.$index,scope.row)">修改</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination class="v3-page" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage4"
:page-sizes="[5,10, 20, 30, 40]" :page-size="5" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
<!-- 添加修改对话框 -->
<!--给el-dialog添加一个mpc-model-middle的class-->
<el-dialog v-model="addOpen" class="diaStyle" style="" :title="title">
<el-form ref="ruleForm" :model="form" :inline="true" :rules="rules" label-width="80px" style="margin-bottom: 20px">
<el-row>
<el-col :span="12">
<el-form-item label="日期" prop="date" style="width: 100%;">
<el-input v-model="form.date" type="text" placeholder="请输入日期" :disabled="disabled" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名" prop="name" style="width: 100%;">
<el-input v-model="form.name" type="text" placeholder="请输入姓名" :disabled="disabled" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="性别" prop="sex" style="width: 100%;">
<el-select v-model="form.sex" placeholder="请选择性别" :disabled="disabled">
<el-option v-for="item in sexOption" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="年龄" prop="age" style="width: 100%;">
<el-input v-model="form.age" type="text" placeholder="请输入年龄" :disabled="disabled" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="联系方式" prop="phone" style="width: 100%;">
<el-input v-model="form.phone" type="text" placeholder="请输入联系方式" :disabled="disabled" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="启用状态" prop="enableFlag" style="width: 100%;">
<el-radio-group v-model="form.enableFlag" :disabled="disabled">
<el-radio v-for="dict in enableOption" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="地址" prop="address" style="width: 100%;">
<el-input v-model="form.address" type="text" placeholder="请输入地址" :disabled="disabled" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm" v-preventReClick="2000" v-if="confDisabled">保 存</el-button>
<el-button @click="closeDialog">{{buttonName}}</el-button>
</div>
</el-dialog>
<child ref="childRef" :parentData="state" :parentFunction="myFunction" style="margin-top: 20px;" />
<div style="border: 2px solid #f708bb;height: 80px;text-align: center;margin-top: 10px">
<el-button size="mini" type="primary" @click="changCount" style="margin-top: 5px;display: flex;justify-content: flex-start;margin-left: 5px;">更改count的值</el-button>
<div>{{ count }}</div>
<div>姓名:{{ user.name }},年龄:{{user.age}}岁</div>
</div>
<div style="border: 2px solid #008000;height: 160px;text-align: center;margin-top: 10px">暂时没想出来写点啥</div>
</div>
</template>
<script setup>
import { toRefs, ref, reactive, watch, unref, computed, onMounted } from 'vue'
import child from './views/child.vue'
import { getCurrentInstance } from 'vue'
import { getTenantDatas } from '@/api/v3'
//使用message
const instance = getCurrentInstance()
const { proxy } = getCurrentInstance();
const data = reactive({
})
const count = ref(0)
const user = reactive({
name: 'zs',
age: 18,
})
function changCount() {
count.value++
user.age++
}
watch(count, (newValue, oldValue) => {
if (newValue) {
instance.proxy.$message({
message: `我侦听到了count状态的变化,当前值为${newValue},从而处理相关逻辑`,
type: 'success',
})
}
})
//深度监听
watch(
user,
(value) => {
console.log(value)
instance.proxy.$message({
message: `我侦听到了user年龄的变化,当前值为${value.age},从而处理相关逻辑`,
type: 'success',
})
},
{
// 深度监听,,,当ref的值是一个复杂数据类型,需要深度监听
deep: true,
immediate: true
}
)
//注册周期钩子:钩子可以用来在组件完成初始渲染并创建 DOM 节点后运行代码
onMounted(() => {
instance.proxy.$message({
message: "生命周期函数:onMounted",
type: 'success',
})
})
const state = reactive({
patientInfo: null,
ActiveIndex: 0,
myData: '我是父组件里的属性',
name: '孩子',
age: '15',
sex: '男',
})
//reactive 和 ref 是 Vue 3 中的两种响应式数据绑定方式,ref 适用于简单的响应式数据,而 reactive 则适用于复杂对象或数组的响应式数据。
//ref:使用 .value 属性来访问和修改值。
//reactive:可以直接访问和修改对象或数组的属性或元素,而无需使用 .value。
let tableData = reactive([])
// 数据相关 ?sortProperty=createdTime&sortOrder=DESC&pageSize=10&page=0
const total = ref(0)
const sortProperty = ref('createdTime')
const sortOrder = ref('DESC')
const pageSize = ref(2)
const page = ref(1)
// 获取数据的方法
const getListData = async () => {
instance.proxy.$message({
message: "获取数据的方法",
type: 'success',
})
const result = await getTenantDatas({
sortProperty: sortProperty.value,
sortOrder: sortOrder.value,
pageSize: pageSize.value,
page: page.value - 1
})
tableData = result
total.value = result.length
}
const handleSizeChange = (val) => {
console.log(`每页 ${val} 条`);
pageSize.value = val
getListData();
}
const handleCurrentChange = () => {
console.log(`当前页: ${val}`);
page.value = val
getListData();
}
// 执行方法
getListData()
//表单校验
let rules = ref({
date: [
{ required: true, message: "日期不能为空", trigger: "blur" },
],
name: [
{ required: true, message: "名称不能为空", trigger: "blur" },
],
address: [
{ required: true, message: "地址不能为空", trigger: "blur" },
],
enableFlag: [
{ required: true, message: "启用状态不能为空", trigger: "blur" },
],
age: [
{ required: true, message: "启用状态不能为空", trigger: "blur" },
],
sex: [
{ required: true, message: "启用状态不能为空", trigger: "blur" },
],
});
// 详情
let form = ref({
});
const ruleForm = ref(null); //表单
let addOpen = ref(false);
let disabled = ref(false);
let buttonName = ref("取 消");
let confDisabled = ref(false);
let title = ref("");
let handleSelect = (index, row) => {
form.value = row;
disabled.value = true;
addOpen.value = true;
confDisabled.value = false;
buttonName.value = "关 闭";
title.value = "查看详情"
}
//修改
let handleUpdate = (index, row) => {
form.value = row;
disabled.value = false;
addOpen.value = true;
confDisabled.value = true;
buttonName.value = "取 消";
title.value = "修改信息"
}
//新增
let handleInsert = () => {
disabled.value = false;
addOpen.value = true;
confDisabled.value = true;
buttonName.value = "取 消";
title.value = "新增信息"
}
/** 提交按钮 */
let submitForm = () => {
const ff = unref(ruleForm);
if (!ff) return;
ruleForm.value.validate((valid) => {
if (valid) {
if (form.value.id != undefined) {
instance.proxy.$message({
message: 'id为:' + form.value.id + '的数据修改成功',
type: 'success',
})
addOpen.value = false;
reset();
} else {
instance.proxy.$message({
message: '新增成功',
type: 'success',
})
addOpen.value = false;
reset();
}
}
});
};
//关闭弹窗
let closeDialog = () => {
addOpen.value = false;
reset();
}
let reset = () => {
form.value = {}
}
let ids = ref(undefined);
let banchParams = ref([]);
//多选框选中数据
let handleSelectionChange = (selection) => {
ids.value = selection.map(item => item.id)
banchParams.value = selection
console.log(ids.value)
}
let enableOption = [
{
"label": "启用",
"value": "0"
}, {
"label": "停用",
"value": "1"
}
];
let enableFlagFormat = (item) => {
return format(enableOption, item.enableFlag);
};
// 回显
let format = (datas, value) => {
var actions = [];
Object.keys(datas).some((key) => {
if (datas[key].value == ('' + value)) {
actions.push(datas[key].label);
return true;
}
})
return actions.join('');
}
let sexOption = [
{
"label": "男",
"value": "0"
}, {
"label": "女",
"value": "1"
}, {
"label": "未知",
"value": "2"
}
];
let sexFormat = (item) => {
return format(sexOption, item.sex);
};
const myFunction = (item) => {
instance.proxy.$message({
message: '我是父组件里的方法',
type: 'success',
})
}
//调用子组件中的方法
const childRef = ref(null);
let handleChild = () => {
childRef.value.changeData();
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.demo {
border: 2px solid #ff0000;
padding: 20px;
}
.v3-page {
margin-top: 5px;
display: flex;
justify-content: flex-end;
}
.dialog-footer{
display: flex;
justify-content: flex-end;
}
</style>
9.2、child.vue
<template>
<div id="example1" class="demo" style="border: 1px solid blue">
<el-button size="mini" type="primary" @click="handleClick()" style="margin-bottom: 10px;display: flex;justify-content: flex-start;margin-left: -15px;">触发父组件方法</el-button>
<el-form :model="dataForm" label-width="80px">
<el-row>
<el-col :span="12">
<el-form-item label="解释" prop="myData" style="width: 100%;">
<el-input v-model="dataForm.myData" type="text" placeholder="请输入解释" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名" prop="name" style="width: 100%;">
<el-input v-model="dataForm.name" type="text" placeholder="请输入姓名" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="性别" prop="sex" style="width: 100%;">
<el-input v-model="dataForm.sex" type="text" placeholder="请输入性别" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="年龄" prop="age" style="width: 100%;">
<el-input v-model="dataForm.age" type="text" placeholder="请输入年龄" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script setup>
import { toRefs, ref, reactive, watch, unref, defineExpose, computed } from 'vue'
import { getCurrentInstance } from 'vue'
//使用message
const instance = getCurrentInstance()
const { proxy } = getCurrentInstance();
const props = defineProps({
parentData: {
type: Object,
default: () => {
return {}
}
},
parentFunction: {
type: Function,
default: () => null,
},
})
//计算属性computed函数
const dataForm = computed(() => props.parentData);
let handleClick = () => {
//父组件中的方法
props.parentFunction(dataForm);
}
//子组件定义方法供父组件调用
const changeData = () => {
instance.proxy.$message({
message: '我是子组件里的方法',
type: 'success',
})
}
defineExpose({
changeData,
});
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
package.json中设置rules
"rules": {
"no-undef": "off",
"no-unused-vars": "off",
"vue/multi-word-component-names": "off"
}