Vue表單快速上手
普通表單
我們先可以創(chuàng)建一個(gè)普通的表單,我們知道的是表單是相對(duì)比較復(fù)雜的,antv被我們?cè)嵅榫褪瞧浔韱?,這個(gè)設(shè)計(jì)出來(lái)的理念就是和別的組件庫(kù)不一樣,我們就在這篇文章分成四個(gè)部分來(lái)講述,現(xiàn)在我們的第一個(gè)部分,就是我們的普通的表單。
操作的步驟:先再main.js引入注冊(cè)Form和Input,在BasicForm拷貝剛才的表單布局,這個(gè)就是最基礎(chǔ)的表單。接下來(lái)就是需要添加一個(gè)錯(cuò)誤校驗(yàn),有對(duì)應(yīng)的屬性傳遞對(duì)應(yīng)的狀態(tài)等。拷貝validateStatus到item中加上對(duì)應(yīng)的help文本,如果想要?jiǎng)討B(tài)輸入的話也可以,給input雙向綁定fieldA和fieldB,在data里面注冊(cè)這兩個(gè)值,同時(shí)validateStatus也變成動(dòng)態(tài)的指向fieldAStatus,文本也是動(dòng)態(tài)指向fieldAHelp。通過(guò)監(jiān)聽(tīng)fieldA的長(zhǎng)度,如果小于5改變狀態(tài)和文本,否則就都置為空就行了。同樣的,給按鈕也綁定一個(gè)事件handleSubmit,拷貝剛才的監(jiān)聽(tīng)邏輯,如果通過(guò)就console.log輸出一下。
如此就完成了一個(gè)最簡(jiǎn)單的表單校驗(yàn),像這種手動(dòng)添加錯(cuò)誤校驗(yàn)信息是最靈活簡(jiǎn)單但是不夠漸變,最好是組件內(nèi)部自動(dòng)校驗(yàn)。
<!--登錄表單區(qū)域--> <el-form ref="loginFormRef" :model="loginForm" :rules="loginFormRules" label-width="0px" class="login_form"> <!--用戶名--> <el-form-item prop="username"> <el-input v-model="loginForm.username" prefix-icon="el-icon-user"></el-input> </el-form-item> <!--密碼--> <el-form-item prop="password"> <el-input v-model="loginForm.password" prefix-icon="el-icon-lock" type="password"></el-input> <!--type="password使得密碼隱藏"--> </el-form-item> <!--按鈕區(qū)域--> <el-form-item class="btns"> <el-button type="primary" @click="login">mua</el-button> <el-button type="info" @click="resetLoginForm">重置</el-button> </el-form-item> </el-form>
<script> export default { data () { return { // 這里是登錄表單數(shù)據(jù) loginForm: { username: 'admin', password: '991130' }, // 表單的驗(yàn)證規(guī)則對(duì)象 loginFormRules: { username: [ { required: true, message: '請(qǐng)輸入登錄名稱', trigger: 'blur' }, { min: 3, max: 10, message: '長(zhǎng)度在 3 到 10 個(gè)字符', trigger: 'blur' } ], password: [ { required: true, message: '請(qǐng)輸入登錄密碼', trigger: 'blur' }, { min: 6, max: 15, message: '長(zhǎng)度在 6 到 15 個(gè)字符', trigger: 'blur' } ] } } }, // 點(diǎn)擊重置按鈕,重置登錄表單 methods: { resetLoginForm () { // console.log(this) this.$refs.loginFormRef.resetFields() }, login () { this.$refs.loginFormRef.validate(async valid => { if (!valid) return const { data: res } = await this.$http.post('login', this.loginForm) if (res.meta.status !== 200) return this.$message.error('登錄失??!') this.$message.success('登錄成功') // 1.將登陸成功之后的token,保存到客戶端的sessionstorage中 // 1.1項(xiàng)目中除了登錄之外的其他api接口,必須在登陸之后才能訪問(wèn) // 1.2token只應(yīng)在當(dāng)前網(wǎng)站打開(kāi)期間生效,所以將token保存在sessionstorage中 window.sessionStorage.setItem('token', res.data.token) // 2.通過(guò)編程式導(dǎo)航跳轉(zhuǎn)到后臺(tái)主頁(yè),路由地址為/home this.$router.push('home') }) } } } </script>
初始數(shù)據(jù)與自動(dòng)校驗(yàn)與動(dòng)態(tài)賦值
目前表單方案主要有兩種,一種是基于雙向綁定的表單校驗(yàn)(iviewelement)另一種就是ant。數(shù)據(jù)加規(guī)則映射到表單視圖,通過(guò)雙向綁定在表單變化的時(shí)候繼續(xù)同步到數(shù)據(jù)中對(duì)比規(guī)則,這個(gè)是理想情況。但是很經(jīng)常是多個(gè)地方使用一個(gè)數(shù)據(jù),使用雙向綁定的話可以實(shí)現(xiàn)表單與其它數(shù)據(jù)一起修改,這可能是想要的,但是也有可能是我們希望表單數(shù)據(jù)提交后經(jīng)過(guò)后臺(tái)等等最后返回出來(lái)的數(shù)據(jù)再進(jìn)行展示,對(duì)這種情況我們就需要復(fù)制或者深復(fù)制一份數(shù)據(jù),這個(gè)就是雙向綁定的模型。Ant選擇把所有數(shù)據(jù)放到表單,data只是提供一個(gè)初始化,后面表單就是一個(gè)黑盒,里面處理的不會(huì)影響外面的數(shù)據(jù),后續(xù)數(shù)據(jù)如果需要同步到data就可以通過(guò)API來(lái)同步到data和其它組件等等。
回到form,在data里面實(shí)例化一個(gè)from(因?yàn)閙ain中有use自動(dòng)把$from掛載到vue實(shí)例上,所以就可以訪問(wèn)到),同時(shí)把this進(jìn)去(用于組件底層內(nèi)部,數(shù)據(jù)改變時(shí)調(diào)用這個(gè)this來(lái)更新當(dāng)前組件也就是basicForm)。把這個(gè)實(shí)例傳遞到最外層那,如此就不需要手動(dòng)監(jiān)聽(tīng)、雙向綁定和watch監(jiān)聽(tīng)了。給input綁定一個(gè)v-decorator,接收數(shù)組,第一個(gè)是字段名稱、第二個(gè)是配對(duì)的規(guī)則(required是否必須,min最小長(zhǎng)度,message報(bào)錯(cuò)信息)、第三個(gè)是初始值的字段。v-decorator的源碼如下,可以看到什么都沒(méi)做,僅僅是提供一個(gè)標(biāo)志位,也就是當(dāng)我們渲染我們的item時(shí),會(huì)查找子組件,如果帶有這個(gè)標(biāo)志位就會(huì)劫持然后交由我們的from去控制
export function antDecorator(Vue) { return Vue.directive('decorator',{}); } export default { // install: Vue =>{ antDecorator(Vue); } }
按鈕的點(diǎn)擊事件也要改一下,通過(guò)form的validateFields,接收err錯(cuò)誤信息和values接收到的值,如果沒(méi)有err說(shuō)明校驗(yàn)通過(guò)。如此就實(shí)現(xiàn)了自動(dòng)校驗(yàn)。接下來(lái)我們想要數(shù)據(jù)改變后同步給data里面的fieldA和fieldB(即后臺(tái)校驗(yàn)通過(guò)后),我們當(dāng)然可以一個(gè)個(gè)賦值,也可以通過(guò)Object.assign往this上賦值即可。如果想通過(guò)接口動(dòng)態(tài)改變表單的值也可以通過(guò)form的setFieldsValueAPI來(lái)動(dòng)態(tài)改變其值,值得注意的是初始化的數(shù)據(jù)只是在第一次生效,后續(xù)改變都要通過(guò)這個(gè)API。
handleSubmit(){ this.form.validateFields((err,value)=> { if(!err) { console.log(values); object.assign(this,values)//全部賦值 } } }
data() { this.form = this.$form.createForm(this)//初始化一個(gè)表單 return { formLauout:'horizontal', fieldA:'hello', fieldB:'' }; } mounted () { setTimeout(() = >{ //定時(shí)改變一次舒適化改變 this.form.setFieldsValue({ fieldA:'byebye'}) },3000) },
發(fā)布表單
結(jié)合vuex和vue-router,建一個(gè)store文件夾在其下面建modules文件夾,下面再建一個(gè)form.js,導(dǎo)入router、request,定義一個(gè)state對(duì)象,下包含step對(duì)象里面只有payAccount即可。定義一個(gè)actions對(duì)象,下面一個(gè)異步的submitStepForm接收{(diào)commit}和{payload},調(diào)用request請(qǐng)求,url是‘/api/form’,方式是post,數(shù)據(jù)是payload,返回請(qǐng)求后我們commit一個(gè)mutation,命名為saveStepFormData,把payload傳過(guò)去,然后路由跳轉(zhuǎn)到‘formep-form/result’結(jié)果頁(yè)。
定義一個(gè)mutations對(duì)象,saveStepFormData接收state和{payload},我們要在里面改變state里面的step值(拓展運(yùn)算符攤開(kāi)step和payload,因?yàn)槔碚撋鲜怯泻芏嗟臄?shù)據(jù))。最后是暴露出這三個(gè)對(duì)象(同時(shí)開(kāi)啟命名空間?。┰趕tore下面再建一個(gè)文件index.js,導(dǎo)入剛才的form.js,在實(shí)例化中加一個(gè)modules對(duì)象,里面丟個(gè)form,如此就完成了store,不過(guò)需要注意的是外面還有一個(gè)store.js(無(wú)用可以刪),而之前的mian.js默認(rèn)是找到這個(gè)store.js(原本是找到剛才新建的index,被外面這個(gè)攔住了),可能會(huì)報(bào)錯(cuò),重啟工程或者指明更清楚的路徑就行。
既然定義了API就往mock里面加多一個(gè)form.js,修改方法為POST,返回?cái)?shù)據(jù)為message即可。接下來(lái)就是正式寫(xiě)表單了,首先是第一個(gè)表單Step1,手寫(xiě)
一個(gè)a-form指定為horizontal,item的label為付款賬戶。往data里面丟一個(gè)布局配置formItemLayout對(duì)象,里面設(shè)置labelCol和wrapperCol,當(dāng)然我們還需要在外面創(chuàng)建一個(gè)form實(shí)例指向當(dāng)前的form,item的labelCol也指向?qū)ο蟮膌abelCol,wrapperCol也指定一下。再加一個(gè)a-input,指定decorator,名稱為payAccount,初始化值需要從vuex中?。梢岳糜?jì)算屬性拿到),規(guī)則是必填否則報(bào)錯(cuò)誤提示。再來(lái)一個(gè)item,里面放button,type為primary,觸發(fā)點(diǎn)擊事件handleSubmit,在方法中定義,先從this中拿到form、$router、$store就不用一個(gè)個(gè)this.,再調(diào)用form的validateFields校驗(yàn)一下,無(wú)錯(cuò)則提交給vuex的store,直接commit而不是dispatch,因?yàn)榈谝徊綗o(wú)需異步,只是儲(chǔ)存數(shù)據(jù)到step字段,給個(gè)type和payload(傳遞values字段),完成后router跳轉(zhuǎn)到第二步(/formep-form-confirm),如此就完成了第一步的表單。接下來(lái)開(kāi)發(fā)這個(gè)第二步的表單,復(fù)制第一步的,把input刪除了,這一步就是要顯示這個(gè)付款賬戶的{{step.payAccount}},再來(lái)個(gè)item,里面放input用來(lái)輸入密碼,type改為password,下一個(gè)item中加多一個(gè)button為提交,另一個(gè)改為上一步,分別綁定handleSubmit和onPrev兩個(gè)事件,上一步的按鈕給個(gè)樣式(margin-left讓它們兩個(gè)有點(diǎn)距離)。onPrev的話是
將路由跳轉(zhuǎn)到‘/formep-form/info’,提交事件的話就是通過(guò)dispatch,來(lái)調(diào)vuex中的actions中的submit最后由其commit來(lái)修改store中的值。注意這里傳值的時(shí)候記得多傳遞一個(gè)第一步的信息(...step、...values),完成之后無(wú)需跳轉(zhuǎn)(因?yàn)閏ommit完就在那里執(zhí)行了跳轉(zhuǎn)的邏輯,不用重復(fù)寫(xiě))。表單三的話給個(gè)小提示就行
<template> <div> <!--面包屑導(dǎo)航區(qū)--> <el-breadcrumb separator-class="el-icon-arrow-right"> <el-breadcrumb-item :to="{ path: '/home' }">首頁(yè)</el-breadcrumb-item> <el-breadcrumb-item>商品管理</el-breadcrumb-item> <el-breadcrumb-item>商品列表</el-breadcrumb-item> </el-breadcrumb> <!-- 卡片視圖區(qū)域 --> <el-card> <el-row :gutter="20"> <el-col :span="8"> <el-input placeholder="請(qǐng)輸入內(nèi)容" v-model="queryInfo.query" clearable> <el-button slot="append" icon="el-icon-search" @click="getGoodsList"></el-button> </el-input> </el-col> <el-col :span="4"> <el-button type="primary" @click="goAddpage">添加商品</el-button> </el-col> </el-row> <!-- table表格區(qū)域 --> <el-table :data="goodslist" border stripe> <el-table-column type="index"> </el-table-column> <el-table-column label="商品名稱" prop="goods_name"></el-table-column> <el-table-column label="商品價(jià)格(元)" prop="goods_price" width="95px"></el-table-column> <el-table-column label="商品重量" prop="goods_weight" width="70px"></el-table-column> <el-table-column label="創(chuàng)建時(shí)間" prop="add_time" width="140px"> <template slot-scope="scope">{{scope.row.add_time | dateFormat}}</template> </el-table-column> <el-table-column label="操作" width="130px"> <template slot-scope="scope"> <el-button size="mini" type="primary" icon="el-icon-edit">編輯</el-button> <el-button size="mini" type="danger" icon="el-icon-delete" @click="removeById(scope.row.goods_id)">刪除</el-button> </template> </el-table-column> </el-table> <!-- 分頁(yè)區(qū)域 --> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="queryInfo.pagenum" :page-sizes="[5, 10, 15, 20]" :page-size="queryInfo.pagesize" layout="total, sizes, prev, pager, next, jumper" :total="total" background> </el-pagination> </el-card> </div> </template> <script> export default { data () { return { queryInfo: { query: '', pagenum: 1, pagesize: 10 }, // 商品列表 goodslist: [], // 總書(shū)記條數(shù) total: 0 } }, created () { this.getGoodsList() }, methods: { // 根據(jù)分頁(yè)獲取對(duì)應(yīng)的商品列表 async getGoodsList () { const { data: res } = await this.$http.get('goods', { params: this.queryInfo }) if (res.meta.status !== 200) { return this.$message.error('獲取商品列表失敗!') } this.$message.success('獲取商品列表成功!') console.log = res.data this.goodslist = res.data.goodslist this.total = res.data.total }, handleSizeChange (newSize) { this.queryInfo.pagesize = newSize this.getGoodsList() }, handleCurrentChange (newPage) { this.queryInfo.pagenum = newPage this.getGoodsList() }, async removeById (id) { const confirmResult = await this.$confirm('此操作將永久刪除該商品, 是否繼續(xù)?', '提示', { confirmButtonText: '確定', cancelButtonText: '取消', type: 'warning' }).catch(err => err) if (confirmResult !== 'confirm') { return this.$message.info('已取消刪除!') } // eslint-disable-next-line no-undef const { data: res } = await this.$http.delete(`goods/${id}`) if (res.meta.status !== 200) { return this.$message.error('刪除失??!') } this.$message.success('刪除成功!') this.getGoodsList() }, goAddpage () { this.$router.push('/goods/add') } } } </script> <style lang="less" scoped> </style>
到此這篇關(guān)于Vue表單快速上手的文章就介紹到這了,更多相關(guān)Vue表單內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue渲染器設(shè)計(jì)實(shí)現(xiàn)流程詳細(xì)講解
在瀏覽器平臺(tái)上,用它來(lái)渲染其中的真實(shí)DOM元素。渲染器不僅能夠渲染真實(shí)的DOM元素,它還是框架跨平臺(tái)能力的關(guān)鍵。所以在設(shè)計(jì)渲染器的時(shí)候一定要考慮好自定義的能力2023-01-01如何在vue3+ts項(xiàng)目中使用query和params傳參
Vue3中的路由傳參有兩種方式:query和params,下面這篇文章主要給大家介紹了關(guān)于如何在vue3+ts項(xiàng)目中使用query和params傳參的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04Vue中的echarts圖表如何實(shí)現(xiàn)loading效果
這篇文章主要介紹了Vue中的echarts圖表如何實(shí)現(xiàn)loading效果,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08vue實(shí)現(xiàn)把接口單獨(dú)存放在一個(gè)文件方式
這篇文章主要介紹了vue實(shí)現(xiàn)把接口單獨(dú)存放在一個(gè)文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08vue實(shí)現(xiàn)簡(jiǎn)單的跑馬燈效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)簡(jiǎn)單的跑馬燈效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10vue2 mint-ui loadmore實(shí)現(xiàn)下拉刷新,上拉更多功能
這篇文章主要介紹了vue2 mint-ui loadmore實(shí)現(xiàn)下拉刷新,上拉更多功能,需要的朋友可以參考下2018-03-03Vue3不支持Filters過(guò)濾器的問(wèn)題
這篇文章主要介紹了Vue3不支持Filters過(guò)濾器的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09vue3+koa實(shí)現(xiàn)文件上傳功能的全過(guò)程記錄
開(kāi)發(fā)項(xiàng)目的時(shí)候,用到文件上傳的功能很常見(jiàn),包括單文件上傳和多文件上傳,下面這篇文章主要給大家介紹了關(guān)于vue3+koa實(shí)現(xiàn)文件上傳功能的相關(guān)資料,需要的朋友可以參考下2023-01-01