是否可以从 Svelte 操作中更新组件变量?
Is it possible to update component variables from within Svelte action?
动作可以更新组件变量吗?例如,在下面的 App.svelte
中,是否可以更新 disabled
和 errors
的值?
<script>
import { form } from './use-form'
let disabled
let errors = {}
const submit = e => {
const formData = new FormData(e.target)
const data = {}
for (let field of formData) {
const [key, value] = field
data[key] = value
}
console.log(data)
e.target.reset()
}
</script>
<form on:submit|preventDefault={submit} use:form={[disabled, errors]}>
<input name="email" type="email" required />
{#if errors && errors.email} <p>{errors.email}</p>{/if}
<input name="password" type="text" minlength="8" required />
{#if errors && errors.password} <p>{errors.password}</p>{/if}
<hr />
<button formnovalidate disabled={!disabled}>submit</button>
</form>
这是 use-form
操作:
export const form = (node, [disabled, errors]) => {
let inputs = node.querySelectorAll('input:invalid')
const handleBlur = event => {
;[...inputs].forEach(e => {
if (e.value.length === 0) {
return
} else {
errors[e.name] = e.validationMessage
}
})
disabled = node.checkValidity()
}
const handleInput = event => {
;[...inputs].forEach(e => {
if (e.value.length === 0) {
return
} else {
errors[e.name] = e.validationMessage
}
})
disabled = node.checkValidity()
}
document.addEventListener('blur', handleBlur, true)
document.addEventListener('input', handleInput, true)
return {
update: (disabled, errors) => {
return disabled, errors
},
destroy: () => {
document.removeEventListener('blur', handleBlur, true)
document.removeEventListener('input', handleInput, true)
},
}
}
为了更好地说明我正在努力实现的目标 here's 排斥一个粗略的工作解决方案,尽管所有内容都夹在一个文件中。
这不起作用,因为 Svelte 不知道它们已更新。你可以做的是
- 向动作添加事件并在组件的回调内进行重新分配:
use:form={{onDisabled: d => disabled = d, ...}}
(在动作调用内 onDisabled(node.checkValidity())
)
- 改用商店,因为 Svelte 会在这些更新时注意到:
let disabled = writable(false); ...
(在操作中执行 disabled.set(node.checkValidity())
)
动作可以更新组件变量吗?例如,在下面的 App.svelte
中,是否可以更新 disabled
和 errors
的值?
<script>
import { form } from './use-form'
let disabled
let errors = {}
const submit = e => {
const formData = new FormData(e.target)
const data = {}
for (let field of formData) {
const [key, value] = field
data[key] = value
}
console.log(data)
e.target.reset()
}
</script>
<form on:submit|preventDefault={submit} use:form={[disabled, errors]}>
<input name="email" type="email" required />
{#if errors && errors.email} <p>{errors.email}</p>{/if}
<input name="password" type="text" minlength="8" required />
{#if errors && errors.password} <p>{errors.password}</p>{/if}
<hr />
<button formnovalidate disabled={!disabled}>submit</button>
</form>
这是 use-form
操作:
export const form = (node, [disabled, errors]) => {
let inputs = node.querySelectorAll('input:invalid')
const handleBlur = event => {
;[...inputs].forEach(e => {
if (e.value.length === 0) {
return
} else {
errors[e.name] = e.validationMessage
}
})
disabled = node.checkValidity()
}
const handleInput = event => {
;[...inputs].forEach(e => {
if (e.value.length === 0) {
return
} else {
errors[e.name] = e.validationMessage
}
})
disabled = node.checkValidity()
}
document.addEventListener('blur', handleBlur, true)
document.addEventListener('input', handleInput, true)
return {
update: (disabled, errors) => {
return disabled, errors
},
destroy: () => {
document.removeEventListener('blur', handleBlur, true)
document.removeEventListener('input', handleInput, true)
},
}
}
为了更好地说明我正在努力实现的目标 here's 排斥一个粗略的工作解决方案,尽管所有内容都夹在一个文件中。
这不起作用,因为 Svelte 不知道它们已更新。你可以做的是
- 向动作添加事件并在组件的回调内进行重新分配:
use:form={{onDisabled: d => disabled = d, ...}}
(在动作调用内onDisabled(node.checkValidity())
) - 改用商店,因为 Svelte 会在这些更新时注意到:
let disabled = writable(false); ...
(在操作中执行disabled.set(node.checkValidity())
)