首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Button按钮--inject与provide

Button按钮--inject与provide

作者头像
用户1148399
发布于 2018-10-11 06:35:10
发布于 2018-10-11 06:35:10
1.2K10
代码可运行
举报
文章被收录于专栏:web前端web前端
运行总次数:0
代码可运行

inject 和 provider 是vue中的组合选项,需要一起使用。目的是允许一个祖先组件向其所有子孙后代注入依赖(简单地说就是祖先组件向子孙后代传值的一种方法,祖先组件通过provider提供变量,子孙后代通过inject注入接收变量)

provider: Object || () => Object

inject: Array || Object

Eg.

button.vue:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1 <template>
 2   <button
 3     class="el-button"
 4     @click="handleClick"
 5     :disabled="buttonDisabled || loading"
 6     :autofocus="autofocus"
 7     :type="nativeType"
 8     :class="[
 9       type ? 'el-button--' + type : '',
10       buttonSize ? 'el-button--' + buttonSize : '',
11       {
12         'is-disabled': buttonDisabled,
13         'is-loading': loading,
14         'is-plain': plain,
15         'is-round': round,
16         'is-circle': circle
17       }
18     ]"
19   >
20     <i class="el-icon-loading" v-if="loading"></i>
21     <i :class="icon" v-if="icon && !loading"></i>
22     <span v-if="$slots.default"><slot></slot></span>
23   </button>
24 </template>
25 <script>
26   export default {
27     name: 'ElButton',
28 
29 //  通过inject向button中注入变量 
30     inject: {
31       elForm: {
32         default: ''
33       },
34       elFormItem: {
35         default: ''
36       }
37     },
38 
39     props: {
40       type: {
41         type: String,
42         default: 'default'
43       },
44       size: String,
45       icon: {
46         type: String,
47         default: ''
48       },
49       nativeType: {
50         type: String,
51         default: 'button'
52       },
53       loading: Boolean,
54       disabled: Boolean,
55       plain: Boolean,
56       autofocus: Boolean,
57       round: Boolean,
58       circle: Boolean
59     },
60 
61     computed: {
62       _elFormItemSize() {
63         return (this.elFormItem || {}).elFormItemSize;
64       },
65       buttonSize() {
66         return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;   
67       },
68       buttonDisabled() {
69         return this.disabled || (this.elForm || {}).disabled; // 通过inject注入的form变量,获得祖先节点form的disabled属性
70       }
71     },
72 
73     methods: {
74       handleClick(evt) {
75         this.$emit('click', evt);
76       }
77     }
78   };
79 </script>

 form.vue:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  1 <template>
  2   <form class="el-form" :class="[
  3     labelPosition ? 'el-form--label-' + labelPosition : '',
  4     { 'el-form--inline': inline }
  5   ]">
  6     <slot></slot>
  7   </form>
  8 </template>
  9 <script>
 10   import objectAssign from 'element-ui/src/utils/merge';
 11 
 12   export default {
 13     name: 'ElForm',
 14 
 15     componentName: 'ElForm',
 16 
 17     // 通过provider向子孙后代注入变量elform,讲this(即form)注入给子孙后代,后代通过获取此变量获取form中的各种配置,如disabled属性等
 18     provide() {
 19       return {
 20         elForm: this
 21       };
 22     },
 23 
 24     props: {
 25       model: Object,
 26       rules: Object,
 27       labelPosition: String,
 28       labelWidth: String,
 29       labelSuffix: {
 30         type: String,
 31         default: ''
 32       },
 33       inline: Boolean,
 34       inlineMessage: Boolean,
 35       statusIcon: Boolean,
 36       showMessage: {
 37         type: Boolean,
 38         default: true
 39       },
 40       size: String,
 41       disabled: Boolean,
 42       validateOnRuleChange: {
 43         type: Boolean,
 44         default: true
 45       },
 46       hideRequiredAsterisk: {
 47         type: Boolean,
 48         default: false
 49       }
 50     },
 51     watch: {
 52       rules() {
 53         if (this.validateOnRuleChange) {
 54           this.validate(() => {});
 55         }
 56       }
 57     },
 58     data() {
 59       return {
 60         fields: []
 61       };
 62     },
 63     created() {
 64       this.$on('el.form.addField', (field) => {
 65         if (field) {
 66           this.fields.push(field);
 67         }
 68       });
 69       /* istanbul ignore next */
 70       this.$on('el.form.removeField', (field) => {
 71         if (field.prop) {
 72           this.fields.splice(this.fields.indexOf(field), 1);
 73         }
 74       });
 75     },
 76     methods: {
 77       resetFields() {
 78         if (!this.model) {
 79           process.env.NODE_ENV !== 'production' &&
 80           console.warn('[Element Warn][Form]model is required for resetFields to work.');
 81           return;
 82         }
 83         this.fields.forEach(field => {
 84           field.resetField();
 85         });
 86       },
 87       clearValidate(props = []) {
 88         const fields = props.length
 89           ? this.fields.filter(field => props.indexOf(field.prop) > -1)
 90           : this.fields;
 91         fields.forEach(field => {
 92           field.clearValidate();
 93         });
 94       },
 95       validate(callback) {
 96         if (!this.model) {
 97           console.warn('[Element Warn][Form]model is required for validate to work!');
 98           return;
 99         }
100 
101         let promise;
102         // if no callback, return promise
103         if (typeof callback !== 'function' && window.Promise) {
104           promise = new window.Promise((resolve, reject) => {
105             callback = function(valid) {
106               valid ? resolve(valid) : reject(valid);
107             };
108           });
109         }
110 
111         let valid = true;
112         let count = 0;
113         // 如果需要验证的fields为空,调用验证时立刻返回callback
114         if (this.fields.length === 0 && callback) {
115           callback(true);
116         }
117         let invalidFields = {};
118         this.fields.forEach(field => {
119           field.validate('', (message, field) => {
120             if (message) {
121               valid = false;
122             }
123             invalidFields = objectAssign({}, invalidFields, field);
124             if (typeof callback === 'function' && ++count === this.fields.length) {
125               callback(valid, invalidFields);
126             }
127           });
128         });
129 
130         if (promise) {
131           return promise;
132         }
133       },
134       validateField(prop, cb) {
135         let field = this.fields.filter(field => field.prop === prop)[0];
136         if (!field) { throw new Error('must call validateField with valid prop string!'); }
137 
138         field.validate('', cb);
139       }
140     }
141   };
142 </script>

form-item.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  1 <template>
  2   <div class="el-form-item" :class="[{
  3       'el-form-item--feedback': elForm && elForm.statusIcon,
  4       'is-error': validateState === 'error',
  5       'is-validating': validateState === 'validating',
  6       'is-success': validateState === 'success',
  7       'is-required': isRequired || required,
  8       'is-no-asterisk': elForm && elForm.hideRequiredAsterisk
  9     },
 10     sizeClass ? 'el-form-item--' + sizeClass : ''
 11   ]">
 12     <label :for="labelFor" class="el-form-item__label" :style="labelStyle" v-if="label || $slots.label">
 13       <slot name="label">{{label + form.labelSuffix}}</slot>
 14     </label>
 15     <div class="el-form-item__content" :style="contentStyle">
 16       <slot></slot>
 17       <transition name="el-zoom-in-top">
 18         <slot 
 19           v-if="validateState === 'error' && showMessage && form.showMessage" 
 20           name="error" 
 21           :error="validateMessage">
 22           <div
 23             class="el-form-item__error"
 24             :class="{
 25               'el-form-item__error--inline': typeof inlineMessage === 'boolean'
 26                 ? inlineMessage
 27                 : (elForm && elForm.inlineMessage || false)
 28             }"
 29           >
 30             {{validateMessage}}
 31           </div>
 32         </slot>
 33       </transition>
 34     </div>
 35   </div>
 36 </template>
 37 <script>
 38   import AsyncValidator from 'async-validator';
 39   import emitter from 'element-ui/src/mixins/emitter';
 40   import objectAssign from 'element-ui/src/utils/merge';
 41   import { noop, getPropByPath } from 'element-ui/src/utils/util';
 42 
 43   export default {
 44     name: 'ElFormItem',
 45 
 46     componentName: 'ElFormItem',
 47 
 48     mixins: [emitter],
 49 
 50     // 通过provider向子孙后代注入变量elform,讲this(即form-item)注入给子孙后代,后代通过获取此变量获取form中的各种配置,如size属性等
 51     provide() {
 52       return {
 53         elFormItem: this
 54       };
 55     },
 56 
 57     inject: ['elForm'],
 58 
 59     props: {
 60       label: String,
 61       labelWidth: String,
 62       prop: String,
 63       required: {
 64         type: Boolean,
 65         default: undefined
 66       },
 67       rules: [Object, Array],
 68       error: String,
 69       validateStatus: String,
 70       for: String,
 71       inlineMessage: {
 72         type: [String, Boolean],
 73         default: ''
 74       },
 75       showMessage: {
 76         type: Boolean,
 77         default: true
 78       },
 79       size: String
 80     },
 81     watch: {
 82       error: {
 83         immediate: true,
 84         handler(value) {
 85           this.validateMessage = value;
 86           this.validateState = value ? 'error' : '';
 87         }
 88       },
 89       validateStatus(value) {
 90         this.validateState = value;
 91       }
 92     },
 93     computed: {
 94       labelFor() {
 95         return this.for || this.prop;
 96       },
 97       labelStyle() {
 98         const ret = {};
 99         if (this.form.labelPosition === 'top') return ret;
100         const labelWidth = this.labelWidth || this.form.labelWidth;
101         if (labelWidth) {
102           ret.width = labelWidth;
103         }
104         return ret;
105       },
106       contentStyle() {
107         const ret = {};
108         const label = this.label;
109         if (this.form.labelPosition === 'top' || this.form.inline) return ret;
110         if (!label && !this.labelWidth && this.isNested) return ret;
111         const labelWidth = this.labelWidth || this.form.labelWidth;
112         if (labelWidth) {
113           ret.marginLeft = labelWidth;
114         }
115         return ret;
116       },
117       form() {
118         let parent = this.$parent;
119         let parentName = parent.$options.componentName;
120         while (parentName !== 'ElForm') {
121           if (parentName === 'ElFormItem') {
122             this.isNested = true;
123           }
124           parent = parent.$parent;
125           parentName = parent.$options.componentName;
126         }
127         return parent;
128       },
129       fieldValue() {
130         const model = this.form.model;
131         if (!model || !this.prop) { return; }
132 
133         let path = this.prop;
134         if (path.indexOf(':') !== -1) {
135           path = path.replace(/:/, '.');
136         }
137 
138         return getPropByPath(model, path, true).v;
139       },
140       isRequired() {
141         let rules = this.getRules();
142         let isRequired = false;
143 
144         if (rules && rules.length) {
145           rules.every(rule => {
146             if (rule.required) {
147               isRequired = true;
148               return false;
149             }
150             return true;
151           });
152         }
153         return isRequired;
154       },
155       _formSize() {
156         return this.elForm.size;
157       },
158       elFormItemSize() {
159         return this.size || this._formSize;
160       },
161       sizeClass() {
162         return this.elFormItemSize || (this.$ELEMENT || {}).size;
163       }
164     },
165     data() {
166       return {
167         validateState: '',
168         validateMessage: '',
169         validateDisabled: false,
170         validator: {},
171         isNested: false
172       };
173     },
174     methods: {
175       validate(trigger, callback = noop) {
176         this.validateDisabled = false;
177         const rules = this.getFilteredRule(trigger);
178         if ((!rules || rules.length === 0) && this.required === undefined) {
179           callback();
180           return true;
181         }
182 
183         this.validateState = 'validating';
184 
185         const descriptor = {};
186         if (rules && rules.length > 0) {
187           rules.forEach(rule => {
188             delete rule.trigger;
189           });
190         }
191         descriptor[this.prop] = rules;
192 
193         const validator = new AsyncValidator(descriptor);
194         const model = {};
195 
196         model[this.prop] = this.fieldValue;
197 
198         validator.validate(model, { firstFields: true }, (errors, invalidFields) => {
199           this.validateState = !errors ? 'success' : 'error';
200           this.validateMessage = errors ? errors[0].message : '';
201 
202           callback(this.validateMessage, invalidFields);
203           this.elForm && this.elForm.$emit('validate', this.prop, !errors, this.validateMessage || null);
204         });
205       },
206       clearValidate() {
207         this.validateState = '';
208         this.validateMessage = '';
209         this.validateDisabled = false;
210       },
211       resetField() {
212         this.validateState = '';
213         this.validateMessage = '';
214 
215         let model = this.form.model;
216         let value = this.fieldValue;
217         let path = this.prop;
218         if (path.indexOf(':') !== -1) {
219           path = path.replace(/:/, '.');
220         }
221 
222         let prop = getPropByPath(model, path, true);
223 
224         this.validateDisabled = true;
225         if (Array.isArray(value)) {
226           prop.o[prop.k] = [].concat(this.initialValue);
227         } else {
228           prop.o[prop.k] = this.initialValue;
229         }
230 
231         this.broadcast('ElTimeSelect', 'fieldReset', this.initialValue);
232       },
233       getRules() {
234         let formRules = this.form.rules;
235         const selfRules = this.rules;
236         const requiredRule = this.required !== undefined ? { required: !!this.required } : [];
237 
238         const prop = getPropByPath(formRules, this.prop || '');
239         formRules = formRules ? (prop.o[this.prop || ''] || prop.v) : [];
240 
241         return [].concat(selfRules || formRules || []).concat(requiredRule);
242       },
243       getFilteredRule(trigger) {
244         const rules = this.getRules();
245 
246         return rules.filter(rule => {
247           if (!rule.trigger || trigger === '') return true;
248           if (Array.isArray(rule.trigger)) {
249             return rule.trigger.indexOf(trigger) > -1;
250           } else {
251             return rule.trigger === trigger;
252           }
253         }).map(rule => objectAssign({}, rule));
254       },
255       onFieldBlur() {
256         this.validate('blur');
257       },
258       onFieldChange() {
259         if (this.validateDisabled) {
260           this.validateDisabled = false;
261           return;
262         }
263 
264         this.validate('change');
265       }
266     },
267     mounted() {
268       if (this.prop) {
269         this.dispatch('ElForm', 'el.form.addField', [this]);
270 
271         let initialValue = this.fieldValue;
272         if (Array.isArray(initialValue)) {
273           initialValue = [].concat(initialValue);
274         }
275         Object.defineProperty(this, 'initialValue', {
276           value: initialValue
277         });
278 
279         let rules = this.getRules();
280 
281         if (rules.length || this.required !== undefined) {
282           this.$on('el.form.blur', this.onFieldBlur);
283           this.$on('el.form.change', this.onFieldChange);
284         }
285       }
286     },
287     beforeDestroy() {
288       this.dispatch('ElForm', 'el.form.removeField', [this]);
289     }
290   };
291 </script>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-10-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
编译时间太长,在IDF5.4版本下,编译个helloworld居然要1000多项,等到地老天荒。。。如果编译遇到问题,简直折磨到怀疑人生,应该选择Arduino库来开发的。
编译时间太长,在IDF5.4版本下,编译个helloworld居然要1000多项,等到地老天荒。。。如果编译遇到问题,简直折磨到怀疑人生,应该选择Arduino库来开发的。
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
前端表单数据那些事
我们可以清晰看到,iview的 form 组件是通过async-validator工具库来作为表单验证的方法
树酱
2020/07/03
1.2K0
前端表单数据那些事
修复uview2.0下表单无法动态校验的问题
3.u-form-item中的表单必须改为 :prop="tableData.${index}.requestQty"
李维亮
2023/09/01
1.8K1
修复uview2.0下表单无法动态校验的问题
Spring+Vue增删改查实例
前端地址:https://github.com/Snowstorm0/SpringAndVue-vue
代码的路
2022/08/23
3920
Spring+Vue增删改查实例
vue2.0+Element-ui实战案例
我们将会选择使用一些 vue 周边的库vue-cli, vue-router,axios,moment,Element-ui搭建一个前端项目案例,后端数据接口,会使用json-server快速搭建一个本地的服务,方便对数据的增删改查,
小周sir
2019/09/23
2.5K0
vue2.0+Element-ui实战案例
vue3+ElementPlus 表单校验
流年Felix
2023/08/15
1.8K0
Vue学习笔记之ElementUI的区间设置
很显然,左侧值是小于右侧值的,但是校验提示仍然报错。究其原因,还是关联校验的问题。既然是关联交验,改变其中一个时应该会重新校验两个。
Jetpropelledsnake21
2023/03/07
9740
Vue学习笔记之ElementUI的区间设置
Vue + Element ui 实现动态表单,包括新增行/删除行/动态表单验证/提交功能
最近通过Vue + Element ui实现了动态表单功能,该功能还包括了动态表单新增行、删除行、动态表单验证、动态表单提交功能,趁热打铁,将开发心得记录下来,方便以后再遇到类似功能时,直接拿来应用。
朱季谦
2023/07/10
5.4K0
vue实战电商管理后台
这里我们使用了 ElementUI 组件 el-container、el-menu
Remember_Ray
2020/10/09
4.7K3
vue实战电商管理后台
element-plus中的表单验证总结
今天使用elment-plus的el-form表单组件提供的验证用户输入的方法,分享出来,方便大家查阅。
用户9914333
2024/02/05
9090
element-plus中的表单验证总结
【摸鱼神器】UI库秒变低代码工具——表单篇(一)设计
表单是很常见的需求,各种网页、平台、后台管理等,都需要表单,有简单的、也有复杂的,但是目的一致:收集用户的数据,然后提交给后端。
用户1174620
2022/06/30
2.6K0
【摸鱼神器】UI库秒变低代码工具——表单篇(一)设计
SpringBoot-Vue 前后端分离开发
vue安装最新版本 npm install -g @vue/cli 或 yarn global add @vue/cli
千羽
2021/01/14
8230
SpringBoot-Vue 前后端分离开发
Element表单验证
要加验证之前一定要确保已经写了 prop 属性,该属性是跟 rule 绑定在一起的,也可以在行内单独制定 rules。
leader755
2022/03/09
3.9K0
手把手教你实现一个Vue无限级联树形表格(增删改)
平时我们可能在做项目时,会遇到一个业务逻辑。实现一个无限级联树形表格,什么叫做无限级联树形表格呢?就是下图所展示的内容,有一个祖元素,然后下面可能有很多子孙元素,你可以实现添加、编辑、删除这样几个功能。
Vam的金豆之路
2021/12/01
6370
手把手教你实现一个Vue无限级联树形表格(增删改)
Element Plus 表单验证详解
Element Plus 是基于 Vue 3 的一套组件库,它提供了许多组件帮助开发者快速构建现代 Web 应用。本文将详细介绍如何在 Element Plus 中进行表单验证,并通过具体示例解释每个部分的用法。
繁依Fanyi
2024/08/02
8150
Vue使用Element实现增删改查+打包
在我们进行项目开发期间,避免不了使用各式各样的组件,Element是由饿了么公司前端团队开源。样式精美、组件齐全、易于上手。
憧憬博客
2020/07/20
2.2K0
9.寻光集后台管理系统-用户管理(注册页面)
进入到http://localhost:2800/#/user_register页面
zx钟
2022/12/02
7240
9.寻光集后台管理系统-用户管理(注册页面)
6. Element Plus前端组件库
Element-UI 是基于 Vue 开发的一套UI组件库,提供丰富网页开发的组件,可快速开发网站,降低前端开发成本。
alexhuiwang
2023/04/24
5.7K0
6. Element Plus前端组件库
Vue核心api和组件开发实践
看完本讲内容,大多数前端初学者就会自以为是地可以在简历写自己"熟练(精通)vue开发“了,最不济也会给自己加个“熟悉掌握vue业务逻辑”的帽子。而对这门课程来说,一切刚刚开始。
一粒小麦
2019/07/18
2.2K0
Vue核心api和组件开发实践
Vue 前后端分离项目(一)
Vue访问永远都是App.vue,然后用<router-view></router-view>开启了一个小窗口进行页面路由,相当于一个容器,用来动态渲染你选择的router。
HLee
2021/06/20
1.7K1
Vue 前后端分离项目(一)
Vue3组件通信相关的知识梳理
我们知道vue3的Composition Api是它几个最大亮点之一,所以下文都是在setup中演示代码的实现。后面会以开发几个简单form组件为例子来演示。
前端达人
2021/08/10
3.8K0
Vue3组件通信相关的知识梳理
相关推荐
前端表单数据那些事
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档