<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                >[success] # 利用通信 仿寫一個form 通信 ~~~ 1.自定義個組件之間傳值就不能再使用'bus'和'vuex' 等系列, 因為'bus' 和 'vuex' 都是項目級別的傳遞,自定義組件無法使用 變依賴'vuex' 或者'bus',因此需要使用組件通信的其他幾種特殊傳遞 2.第一種常見的父子傳遞'props' 父傳子,'$emit' 控制父組件的某個方法, 讓控制父組件的某個方法將從子組件傳遞過來的值重新賦值形成'子傳父'。 3.第二種'vue' api文檔中的'provide' / 'inject' ,'提供'/'注入', 這種只能'父傳子',但不僅限'父傳子'甚至'爺傳孫'可以理解成 是一個加強版的'props'。 3.第三種'mixins' 混入繼承,這種有點投機取巧適合接口,也就是提取出一個 公共的功能,在對應需要該接口的位置進行調用即可,這種不是傳統意義父子 傳值,更像是因為組件使用的數據來自一個接口,大家或者這個這接口數值 導致數據一致 4.利用自己的寫的 'dispatch' 和 'broadcast' 進行傳值,分別是'子孫像父組件' '父組件像子孫傳值',利用的原理是'$on' 和 '$emit' ~~~ >[info] ## 分析前輩們form 組件 -- iview ~~~ 1.根據下面代碼可以分析實際這個form組件是由兩個組件構成的,分別是'Form' 和'FormItem' 組件構成的 2.'Form' 中有兩個值分別是'model'和'rules' 依次表示是'對應的字段'和'表單驗證規則' 3.'FormItem' 中的'prop' 對應著'model' 中的某個字段,'FormItem'中有個插槽可以填充, 各個輸入框 ~~~ ~~~ <template> <div> <Form ref="formInline" :model="formInline" :rules="ruleInline" inline> <FormItem prop="user"> <Input type="text" v-model="formInline.user" placeholder="Username"> <Icon type="ios-person-outline" slot="prepend"></Icon> </Input> </FormItem> </Form> </div> </template> <script> export default { name: 'home', data(){ return{ formInline: { user: '', }, ruleInline: { user: [ { required: true, message: 'Please fill in the user name', trigger: 'blur' } ], } } } } </script> ~~~ >[info] ## 開始定義自己form ~~~ 1.根據上面分析,需要三個組件分別是'Form','Form-item','Input' 2.思路,定義驗證規則傳入給'Form','Form' 將規則分發給不同的'FormItem' ,每個'FormItem' 去進行驗證 3.組件目錄 │ ├── 'components' // 存放組件文件夾 │ │ └── 'Form' // 存放對iview 二次封裝文件 │ │ └─ 'myFromItem.vue' // 每個單獨輸入框驗證組件 │ │ └─ 'myFrom.vue' // 配置驗證規則和字段 4.使用組件通信(三)中自定義封裝的方法 ~~~ >[danger] ##### 先自定義個一個input 輸入框組件 ~~~ 1.常用v-model 綁定input,'v-model' 是一個語法糖,實際':value' 和'@input' 一個縮寫,隱藏在寫自己的input組件的時候需要拆開來定義 2.'input' 觸發有兩種一種是'input' 也就是輸出就觸發,'blur' 失去焦點觸發, 因此組件觸發要留出這兩個觸發事件,三還可以增加'change'事件 3.blur:失去焦點時觸發,常見的有輸入框失去焦點時觸發校驗; change:實時輸入時觸發或選擇時觸發,常見的有輸入框實時輸入時觸發校驗、 下拉選擇器選擇項目時觸發校驗等。 ~~~ ~~~ <template> <input type="text" :value="currentValue" @blur="handleBlur" @input="handleInput"> </template> <script> import Emitter from '../../mixins/emitter.js'; export default { mixins:[Emitter], props:{ // 接受父傳子 過來的值,因為v-mode 是:value 和 @input的縮寫 value:{ type:String, default:'' } }, data(){ return{ currentValue:this.value } }, methods:{ handleInput (event) { // 通過event 獲取當前值傳遞給父組件 const value = event.target.value; this.currentValue = value; this.$emit('input', value); // 通過 自定義子傳父 的方式 將自定義的觸發名'on-form-change'傳遞給formItem this.dispatch('iFormItem', 'on-form-change', value); }, handleBlur () { // 通過 自定義子傳父 的方式 將自定義的觸發名'on-form-change'傳遞給formItem this.dispatch('iFormItem', 'on-form-blur', this.currentValue); } } } </script> ~~~ >[danger] ##### myFromItem.vue 設計 * 編寫組件第一步從樣式布局 和 生命周期要做的下手 ~~~ 1.html 的設計需要有label 和一個插槽,其中插槽用來和各種類型的input組 合,'當字段必填的時候' 需要給字段加一個紅星 2.根據前輩的分裝可以發現'FormItem' 主要填了'prop' 和 'label'也就是依次對 應在form 傳入的規則字段,和label 需要展示的名字 3.分析生命周期要做的事,首先要知道父子組件的生命周期調用的順序: vm.created -》vm.beforedMount-》child.created-》child.beforeMount -》child.mounted-》vm.mounted 根據上面分析簡單的首先子組件的生命周期是最先執行完畢的簡單的說, 最外層的父組件最開始 會調用自己的created 和beforedMount等生命周期 然后對應最內層的子組件會調用自己的完整的周期,然后再執行父組的'mounted' 生命周期 4.首先我們需要將子組件內容傳遞給父組件,也就是要將'FormItem' 中的內容傳遞給 'Form' 組件中,父傳子的幾種方式中我們選著我們自定義的寫的封裝方法傳遞, 讓其直接觸發的方式也有幾種'生命周期','計算屬性','watch監聽',我們不需要吧所有 的'FormItem' 對象傳遞過去,也就是有'prop' 需要驗證的傳遞給'Form' 組件 ,需要對 規則'Form' 中有'rules' 規則的字段加※號,關于觸發'input' 傳遞過來的子傳父調用 也應當在'mounted '聲明周期,因為$on要想綁定監聽就需要在生命周期中 4.1 總結上面 在'mounted' 生命周期要做的,將'FormItem' 對象子傳父給'Form', 將'Form中的規則獲取'并且如果是必填項將加上※,將獲取input傳遞過來的觸發事件 用$on 監聽上,也就是'input' 和'blur' 事件中的方法 4.2 為了明確容易區分 分別定義了'getRules' 用來獲取'Form' 父組件中的規則,和'setRules' 給'FormItem' 中必填項加※ 5.當前生命周期結束后提供 給父組件一個效果 的方法 ~~~ ~~~ <template> <div> <label v-if="label" :class="{ 'i-form-item-label-required': isRequired }">{{label}}</label> <slot></slot> </div> </template> <script> import Emitter from '../../mixins/emitter.js'; export default { name: "mFormItem", mixins:[Emitter], inject:['form'], props:{ label: { type: String, default: '' }, prop:{ type:String, }, }, data(){ return{ isRequired:false } }, methods:{ // 通過inject 接收form 中驗證規則,獲取對應字段驗證條件 getRules(){ let formRules = this.form.rules // 如果有就獲取當前字段的規則 formRules = formRules ? formRules[this.prop] :[] // concat 會生成新的數組返回 return [].concat(formRules || []) }, // 獲取規則操作給dom 加紅色星星標記 和獲取input 組件綁定的觸發事件 setRules(){ let rules = this.getRules(); // 拿到 數組做是否有內容在做循環 if(rules.length){ // 循環每一項 在規則對象中看是否存在required 也就是必填 // 來看是否加星 rules.every((rule) => { // 如果當前校驗規則中有必填項,則標記出來 this.isRequired = rule.required; }); } // 將 父組件對象事件 單獨提取出來寫成方法 this.$on('on-form-blur', this.onFieldBlur); this.$on('on-form-change', this.onFieldChange); }, }, mounted(){ // 如果有prop 驗證字段就將當期formItem 傳遞給Form if(this.prop){ this.dispatch('mForm', 'on-form-item-add', this) // 如果有調用 setRules 方法 this.setRules(); } }, // 組件銷毀前,將實例從 Form 的緩存中移除 beforeDestroy () { this.dispatch('iForm', 'on-form-item-remove', this); } } </script> <style scoped> .i-form-item-label-required:before { content: '*'; color: red; } .i-form-item-message { color: red; } </style> ~~~ * 第二步 從完善功能下手 ~~~ 1.上面已經從'Form' 獲取當前'Form' 字段的驗證,并對必填項做了處理,這 吧就需要獲取當前驗證的觸發方式,如果有則繼續執行 2.需要使用一個第三方的驗證庫,來專門驗證一些表單規則'async-validator' 3.考慮重置功能,重置的數據也是form 的model 里面提供的因此,在item最開始, 生命周期初始的時候 就應該 保存要被重置的內容 ~~~ * 最終完整代碼 ~~~ <template> <div> <label v-if="label" :class="{ 'i-form-item-label-required': isRequired }">{{label}}</label> <slot></slot> <div v-if="validateState === 'error'" class="i-form-item-message">{{ validateMessage }}</div> </div> </template> <script> import Emitter from '../../mixins/emitter.js'; import AsyncValidator from 'async-validator'; export default { name: "mFormItem", mixins:[Emitter], inject:['form'], props:{ label: { type: String, default: '' }, prop:{ type:String, }, }, data(){ return{ isRequired: false, // 是否為必填 加星星 validateState: '', // 校驗狀態 validateMessage: '', // 校驗不通過時的提示信息 } }, computed: { // 從 Form 的 model 中動態得到當前表單組件的數據 fieldValue () { return this.form.model[this.prop]; } }, methods:{ // 通過inject 接收form 中驗證規則,獲取對應字段驗證條件 getRules(){ let formRules = this.form.rules // 如果有就獲取當前字段的規則 formRules = formRules ? formRules[this.prop] :[] // concat 會生成新的數組返回 return [].concat(formRules || []) }, // 獲取規則操作給dom 加紅色星星標記 和獲取input 組件綁定的觸發事件 setRules(){ let rules = this.getRules(); // 拿到 數組做是否有內容在做循環 if(rules.length){ // 循環每一項 在規則對象中看是否存在required 也就是必填 // 來看是否加星 rules.every((rule) => { // 如果當前校驗規則中有必填項,則標記出來 this.isRequired = rule.required; }); } // 將 父組件對象事件 單獨提取出來寫成方法 this.$on('on-form-blur', this.onFieldBlur); this.$on('on-form-change', this.onFieldChange); }, // 獲取'Form' 中 'rules' 觸發驗證規則是否是規定的 blur 和 change getFilterRule(tigger){ const rules = this.getRules(); // 沒填寫驗證規則 或者驗證規則等于blur和change 的驗證獲取到 return rules.filter(rule => !rule.trigger || rule.trigger.indexOf(trigger) !== -1); }, // 開始驗證 validate(trigger, callback = function () {}){ let rules = this.getFilteredRule(trigger); // 不符合 當前驗證 則不往下執行 if (!rules || rules.length === 0) { return true; } // 設置狀態為校驗中 如果是erro 則顯示報錯信息 this.validateState = 'validating'; // 使用第三方驗證庫來驗證我們傳入的規則 // 以下為 async-validator 庫的調用方法 let descriptor = {}; descriptor[this.prop] = rules; const validator = new AsyncValidator(descriptor); let model = {}; // 在計算屬性中獲取 當前輸入框的內容this.fieldValue model[this.prop] = this.fieldValue; validator.validate(model, { firstFields: true }, errors => { this.validateState = !errors ? 'success' : 'error'; this.validateMessage = errors ? errors[0].message : ''; callback(this.validateMessage); }); }, onFieldBlur() { this.validate('blur'); }, onFieldChange() { this.validate('change'); }, // 重置數據 resetField () { this.validateState = ''; this.validateMessage = ''; this.form.model[this.prop] = this.initialValue; }, }, mounted(){ // 如果有prop 驗證字段就將當期formItem 傳遞給Form if(this.prop) { this.dispatch('mForm', 'on-form-item-add', this) // 如果有調用 setRules 方法 this.setRules(); // 設置初始值,以便在重置時恢復默認值 this.initialValue = this.fieldValue; } }, // 組件銷毀前,將實例從 Form 的緩存中移除 beforeDestroy () { this.dispatch('iForm', 'on-form-item-remove', this); } } </script> <style scoped> .i-form-item-label-required:before { content: '*'; color: red; } .i-form-item-message { color: red; } </style> ~~~ >[danger] ##### Form 組件分析 * 從生命周期開始下手 ~~~ 1.在'FormItem' 的生命周期中提供了傳遞給form組件的,當前對象的方法, 因此在'Form' 的生命周期開始的時候去接收,因為每個'FormItem' 是相互 獨立的因此需要將他們統一保存起來,調用他們的重置和驗證功能 2.我們剛才重置和驗證都是給每個單獨的'FormItme'做的,簡單的說他們的 觸發條件就是失去焦點和數據改變,因此有時候我們需要點擊提交按鈕 才觸發判斷每一個'FormItem' 是否好用,因此我們的'validate' 是驗證所有的 3.代碼的講解 ~~~ ~~~ <template> <form> <slot></slot> </form> </template> <script> export default { name: 'mForm', props: { model: { type: Object }, rules: { type: Object }, }, provide() { return { form : this }; }, data () { return { fields: [] }; }, methods: { // 公開方法:全部重置數據 resetFields() { this.fields.forEach(field => { field.resetField(); }); }, // 公開方法:全部校驗數據,支持 Promise validate(callback) { return new Promise(resolve => { let valid = true; let count = 0; this.fields.forEach(field => { // 調用'Formitem' 中的驗證方法,第二個參數是回調函數 // 驗證的方法 如果沒有target也就是觸發判斷的第一個參數為空或者是指定的'change'和'blur'都會觸發 // 現在獲取了每一個'FormItem' 中的驗證是否正確并且調用回調可以觸發我們自己規則 // 使用Promise 是為了支持異步 field.validate('', errors => { if (errors) { valid = false; } if (++count === this.fields.length) { // 全部完成 resolve(valid); if (typeof callback === 'function') { callback(valid); } } }); }); }); } }, created () { this.$on('on-form-item-add', (field) => { if (field) this.fields.push(field); }); this.$on('on-form-item-remove', (field) => { if (field.prop) this.fields.splice(this.fields.indexOf(field), 1); }); } } </script> ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看