Svelte能否从插槽组件或父布局修改布局文件内的属性?
回答
默认情况下两个位置都不能直接修改routes/home/__layout.svelte中定义的activeId变量,具体原因和可行实现方案分情况说明:
针对插槽子组件
routes/home/content.svelte
子组件是被布局内的<slot />渲染的路由内容,和布局之间没有做显式绑定的话,根本访问不到布局的内部作用域,自然没法直接修改变量。
最省事的实现方式是用Svelte内置的context能力:
在routes/home/__layout.svelte中把变量和修改方法放到context里下发:<script> import { setContext } from 'svelte' let activeId // 把修改方法一起传下去,不要直接把变量传下去让外部改 const updateActiveId = (newId) => { activeId = newId } setContext('homeLayoutCtx', { activeId, updateActiveId }) </script> <!-- 原有布局内容 --> <slot />之后在
content.svelte里通过getContext拿到修改方法,调用就能更新布局里的activeId:<script> import { getContext } from 'svelte' const { updateActiveId } = getContext('homeLayoutCtx') // 比如点击某个导航项的时候调用 const handleNavClick = (id) => { updateActiveId(id) } </script>如果只是单层插槽传值,也可以用插槽props、自定义事件的方式实现,但是路由嵌套层级深的话context更方便。
针对上层父布局
routes/__layout.svelte
Svelte默认是父到子的单向数据流,父布局是外层组件,没法直接访问内层子布局(home布局)的内部变量,直接修改是做不到的。
两种常用实现方案:- 父布局通过props向下传递控制值,home布局声明接收对应props,再把props的变化同步到内部的
activeId上。如果嵌套层级多不想层层传props,可以用第二种方案。 - 把
activeId抽到全局Svelte store里维护,不管是父布局、home布局还是子路由组件,都直接引入store读写状态,不用做跨组件传值,适合跨多组件共享的状态场景。
- 父布局通过props向下传递控制值,home布局声明接收对应props,再把props的变化同步到内部的
别想着用
bind:this拿组件实例直接改内部变量,这种写法完全破坏组件封装,后续迭代很容易出难以排查的问题,不要用。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

