本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一工夫和你分享前端行业趋势,学习路径等等。
更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi ,蕴含一线大厂面试残缺考点、材料以及我的系列文章。
最近,每当组件的内容(插槽、子组件等)发生变化时,我须要更新它的状态。对于上下文,它是一个表单组件,用于跟踪其输出的有效性状态。
上面的代码片段是以Options
API格局编写的,但除了指定的中央外能够在Vue2 和 Vue2中应用。
开始
先从管制表单状态开始,依据状态批改一个类,孩子内容应用<slot/>
填充:
<template> <form :class="{ '--invalid': isInvalid }"> <slot /> </form></template><script>export default { data: () => ({ isInvalid: false, }),};</script>
为了更新isInvalid
属性,咱们须要增加一个触发的事件,能够应用 sumit
事件 ,但我更喜用 input
事件。
表单事件7个: focus, blur, input, select, change, reset, submit 等,具体详解看这篇文章:https://blog.csdn.net/qq_4379...
表单不会触发 input
事件,但咱们能够应用 "事件委托"。咱们将监听器附加到父元素(<form>
)上,当事件产生在它的子元素(<input>
、<select>
、<textarea>
等)上时就会被触发。
任何时候在这个组件的<slot>
中触发input
事件,表单将捕捉该事件。
<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot /> </form></template><script>export default { data: () => ({ isInvalid: false, }), methods: { validate() { // 验证逻辑 } }};</script>
验证逻辑能够是简略或简单的。本文为了演示,用简略的办法,应用form.checkValidity()
API 来查看表单是否基于HTML验证属性而无效。
为了拜访<form>
元素。能够用refs
或$el
属性。为了简略起见,本文应用$el
。
<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot /> </form></template><script>export default { data: () => ({ isInvalid: false, }), methods: { validate() { this.isInvalid = !this.$el.checkValidity() } }};</script>
问题
这里有一点问题。如果表单的内容扭转了,会产生什么?如果一个<input>
在表单加载被增加到DOM中,会产生什么?
举个例子,咱们把这个表单组件称为 "MyForm"
,在 App 中,内容如下:
// App.vue<template> <MyForm> <input v-model="showInput" id="toggle-name" name="toggle-name" type="checkbox" /> <label for="toggle-name">显示其它 input</label> <template v-if="showInput"> <label for="name">Name:</label> <input id="name" name="name" required /> </template> <button type="submit">提交</button> </MyForm></template><script>import Form from "./components/form.vue";export default { name: "App", components: { MyForm: Form, }, data: () => ({ showInput: false, }),};</script>
当App.vue
通过条件来暗藏显示某些 input
,咱们的表单须要晓得。在这种状况下,咱们会想到在表单内容发生变化时跟踪其有效性,而不仅仅是在 input
事件或mounted
生命周期钩子上。否则,可能会显示不正确的信息。
相熟 Vue的生命周期钩子小伙伴,这里可能会想到应用 update
来跟踪变动。实践上,这听起来不错。在实践中,它会发明一个有限的循环,而后浏览器挂了。
解决办法
通过一番钻研和测试,最佳解决方案是应用MutationObserver
API。它是浏览器内置的办法,提供了监督对DOM树所做更改的能力,如果节点的增减、属性的变动、文本内容的变动,这个 API 都能够失去告诉。
它是原生的办法,所以不受限于框架。
应用时,首先应用MutationObserver
构造函数,新建一个观察器实例,同时指定这个实例的回调函数。在每次 DOM 变动后调用,这个回调都被调用。该回调函数承受两个参数,第一个是变动数组,第二个是观察器实例,将咱们的 form
组件改写成如下:
<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot /> </form></template><script>export default { data: () => ({ isInvalid: false, }), mounted() { const observer = new MutationObserver(this.validate); observer.observe(this.$el, { childList: true, subtree: true, }); this.observer = observer; }, methods: { validate() { this.isInvalid = !this.$el.checkValidity(); }, }, beforeUnmount() { this.observer.disconnect(); },};</script><style scoped></style>
这里还须要应用 beforeUnmount
生命周期事件来断开observer
的连贯,这会革除它所调配的任何内存。
最初,咱们将isInvalid
状态传递给要拜访的内容的插件槽,这也称作用域的槽,它十分有用。
<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot v-bind="{ isInvalid }" /> </form></template><script>export default { data: () => ({ isInvalid: false, }), mounted() { const observer = new MutationObserver(this.validate); observer.observe(this.$el, { childList: true, subtree: true, }); this.observer = observer; }, methods: { validate() { this.isInvalid = !this.$el.checkValidity(); }, }, beforeUnmount() { this.observer.disconnect(); },};</script>
通过这样的设置,能够在咱们的表单组件中增加任意数量的 input
,并增加任何它须要的条件渲染逻辑。只有input
应用HTML验证属性,表单就会跟踪它是否处于无效状态。
此外,因为应用的是作用域槽,咱们将表单的状态提供给父级,所以父级能够对有效性的变动做出反馈。
例如,在 App.vue
,咱们想在表单有效时 "禁用" 提交按钮,能够这么来写
<template> <MyForm> <template slot:default="form"> <label for="name">Name:</label> <input id="name" name="name" required> <button type="submit" :class="{ disabled: form.isInvalid }" > Submit </button> </template> </MyForm></template>
nice~.
心愿本文能对你将来的开必有所帮忙。
~完,我是小智,筹备来场按摩,秀起来!
作者:Dmitri Pavlutin 译者:前端小智 起源:Dmitri Pavlutin
原文:https://austingil.com/watchin...
代码部署后可能存在的BUG没法实时晓得,预先为了解决这些BUG,花了大量的工夫进行log 调试,这边顺便给大家举荐一个好用的BUG监控工具 Fundebug。
交换
有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。