- 校验整个表单
- 校验自定义组件的值
- 校验单独的某个字段,可参考:element el-form 表单校验单个字段 this.$refs.form.validateField 单独校验
- 自定义校验表单方式(
一定要调用callback,不然走后面的校验流程了,现象就是:因为没有在自定义的validator后面缺少调用callback(),导致后面校验整体表单的时候,它没有进form.validate((valid)=>{ // 代码没有进到这里来 })
,可参考:el-form表单校验无效) - 当不同的路由来到同一组件时,可以通过监听路由的方式,来加载数据,可参考:vue中多个路由对应同一个组件,页面切换不刷新问题
<template>
<div class="main-box">
<div class="title">发表文章</div>
<div style="display:flex;flex-direction: column;flex: 1;overflow: hidden;">
<div style="display:flex;margin-bottom: 10px;">
<el-input ref="articleTitleRef" v-model="article.articleTitle" placeholder=""
style="flex:1;margin-right: 15px;"></el-input>
<div>
<el-button type="danger" plain style="width:100px;">保存草稿</el-button>
<el-button type="danger" style="width:100px;" @click="preparePublishArticle">发布文章</el-button>
</div>
</div>
<div style="flex: 1;overflow: hidden;border: 1px solid #dddddd;">
<VMdEditor ref="articleContentRef" v-model="article.mdContent"
@contentChange="e => article.htmlContent = e.html" />
</div>
</div>
<Dialog @close="handleCloseDialog" @confirm="handleConfirm" :dialog="dialog" width="600px">
<el-form ref="articleFormRef" :model="article" :rules="articleFormRules" label-width="80px">
<el-form-item prop="categoryId" label="文章分类">
<el-tree-select v-model="article.categoryId" check-strictly default-expand-all
:data="categoryTreeSelectData" placeholder="请选择文章分类" :props="defaultProps"
:render-after-expand="false" style="width: 100%;" />
</el-form-item>
<el-form-item prop="tagIdList" label="文章标签">
<div>
<el-tag @close="handleCloseTag(tag)" closable v-for="tag in tagList" :key="tag.id" class="tag">{{ tag.tagName }}</el-tag>
</div>
<el-popover v-if="tagAddable" placement="bottom-start" :width="480" trigger="click">
<template #reference>
<el-button type="success" size="small" v-if="tagAddable" plain>添加标签</el-button>
</template>
<template #default>
<div class="article-tag-box">
<div class="tag-box-header">标签</div>
<el-input v-model="tagInput" @keyup.enter.native="handleTagInput" placeholder="输入标签名,按enter可添加新的标签"></el-input>
<div style="margin:10px 0;" >添加标签</div>
<div class="tags-wrapper">
<el-tag v-for="tag in allTags" :key="tag.id"
@click="addTagToArticle(tag)"
:type="isTagSelected(tag.id)?'info':''"
:style="{ cursor: isTagSelected(tag.id)?'not-allowed':'pointer', 'margin': '0 10px 10px 0' }">
{{ tag.tagName }}
</el-tag>
</div>
</div>
</template>
</el-popover>
</el-form-item>
<el-form-item prop="articleCover" label="上传封面">
<div class="article-cover">
<article-cover-upload v-model="article.articleCover"/>
</div>
</el-form-item>
<el-form-item prop="isTop" label="置顶">
<el-switch
v-model="article.isTop"
:inactive-value="1"
:active-value="0"
inline-prompt
active-text="是"
inactive-text="否"
/>
</el-form-item>
<el-form-item prop="isSeen" label="是否可见">
<el-radio-group v-model="article.isSeen">
<el-radio :label="1">公开</el-radio>
<el-radio :label="2">私密</el-radio>
<el-radio :label="3">评论可见</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</Dialog>
</div>
</template>
<script>
export default {
name: 'ArticlePublish'
}
</script>
<script setup>
import VMdEditor from '@/components/VMdEditor.vue'
import Pagination from '@/components/Pagination.vue'
import { ref, reactive, onMounted, computed,watch } from 'vue'
import Messager from '@/utils/messager'
import MsgBoxer from '@/utils/msgBoxer'
import { useRouter } from 'vue-router'
import { publishArticle as publishArticleApi } from '@/api/articleApi'
import Dialog from '@/components/Dialog.vue'
import { queryCategoryTreeList } from '@/api/categoryApi'
import { listAllTag,createTag } from '@/api/tagApi'
import ArticleCoverUpload from '@/components/ArticleCoverUpload.vue'
const router = useRouter()
let article = ref({
articleTitle: '1',
mdContent: `1`,
htmlContent: '',
tagIdList: [],
categoryId: null,
isTop: 0,
isSeen: 1,
})
let tagList = ref([])
let articleFormRules = {
categoryId: [
{ required: true, message: '请选择分类id', trigger:'blur'}
],
tagIdList: [
{ validator: (rule,value,callback)=>{
if(!value || value.length == 0) {
callback(new Error('请至少添加一个标签'))
}else {
callback() // 注意, 这里需要调用callback, 一定要写, 否则后面会进不了后面字段的校验
// 见:el-form表单校验无效 - https://blog.csdn.net/monparadis/article/details/117110627
}
}
, trigger:'blur' }
],
articleCover: [
{ validator: (rule,value,callback)=>{
if(!value) {
callback(new Error('来张图片作封面?'))
}else {
callback()
}
}
, trigger:'blur' }
],
}
const articleContentRef = ref(null)
const articleTitleRef = ref(null)
let dialog = ref({
title: '发布文章',
visible: false,
})
function preparePublishArticle() {
console.log(article.value);
if (!article.value.articleTitle) {
Messager.error('文章标题不能为空')
articleTitleRef.value.focus()
return
}
if (!article.value.mdContent) {
Messager.error('文章内容不能为空')
articleContentRef.value.focus()
return
}
dialog.value.visible = true
}
const articleFormRef = ref(null)
// 确认发布文章
function handleConfirm() {
console.log('111');
// debugger
articleFormRef.value.validate((valid)=>{
// debugger
console.log('valid',valid);
if(!valid) {
console.log('校验不通过');
return
}
console.log('校验通过');
publishArticleApi(article.value).then(res=>{
Messager.ok('发布成功')
})
})
}
function handleCloseDialog() {
articleFormRef.value.clearValidate(); // 清空表单验证
}
let defaultProps = {
children: 'children',
label: 'categoryName',
value: 'id'
}
let categoryTreeSelectData = ref([])
function getCategoryTreeList() {
queryCategoryTreeList({}).then(res => {
categoryTreeSelectData.value = res
})
}
function getAllTags() {
listAllTag().then(res => {
allTags.value = res
})
}
onMounted(() => {
getCategoryTreeList()
getAllTags()
})
const allTags = ref([])
const tagInput = ref('')
let tagAddable = computed({
get() {
return tagList.value.length < 6
}
})
function handleTagInput() {
if(tagList.value.length > 6) {
Messager.warn('文章已经添加够多的标签了')
return
}
createTag({tagName:tagInput.value}).then(res=>{
getAllTags()
tagList.value.push(res)
article.value.tagIdList = tagList.value.map(tag=>tag.id)
})
}
function addTagToArticle(tag) {
let tagIds = tagList.value.map(tag => tag.id)
if(tagIds.indexOf(tag.id) != -1) {
return
}
tagList.value.push(tag)
article.value.tagIdList = tagList.value.map(tag=>tag.id)
}
function isTagSelected(tagId) {
return tagList.value.map(tag => tag.id).indexOf(tagId) != -1
}
function handleCloseTag(tag) {
tagList.value.splice(tagList.value.map(tag=>tag.id).indexOf(tag.id),1)
article.value.tagIdList = tagList.value.map(tag=>tag.id)
}
// 当表单数据发生变化时,就校验具体的表单字段
watch(()=>article.value.tagIdList,(newValue,oldValue)=>{
articleFormRef.value.validateField('tagIdList')
})
watch(()=>article.value.articleCover,(newValue,oldValue)=>{
articleFormRef.value.validateField('articleCover')
})
watch(()=>article.value.categoryId,(newValue,oldValue)=>{
articleFormRef.value.validateField('categoryId')
})
</script>
<style lang="scss" scoped>
.main-box {
display: flex;
flex-direction: column;
}
.article-tag-box {
height: 200px;
display: flex;
flex-direction: column;
.tag-box-header {
text-align: center;
margin: 10px 0;
}
.tags-wrapper {
flex: 1;
overflow: auto;
}
}
.tag {
margin: 5px 10px 5px 0;
}
.article-cover {
width: 360px;
height: 180px;
}
</style>
文章来源地址https://www.toymoban.com/news/detail-437381.html
文章来源:https://www.toymoban.com/news/detail-437381.html
到了这里,关于el表单字段校验问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!