插槽内容在子组件作用域中编译,无法直接使用父组件局部过滤器;全局过滤器虽可用,但非插槽传递所致;推荐通过作用域插槽暴露数据,由父组件在v-slot中应用过滤器。

子组件插槽内容里不能直接用父组件过滤器
插槽(<slot>)本身不继承父组件的 filters 选项,哪怕你在父组件的 filters 里定义了 formatDate,在插槽内部写 {{ date | formatDate }} 也会报错或渲染为空——因为模板编译时,插槽内容是在**子组件作用域**下解析的,而子组件没注册这个过滤器。
为什么全局过滤器在插槽里有时“看起来能用”
这不是插槽的功劳,而是你误用了全局过滤器:
-
Vue.filter("formatDate", ...)注册的是全局过滤器,所有组件模板(包括子组件内部、插槽内容)都能访问 - 但如果你只在父组件的
filters选项里写了formatDate,那它只是局部过滤器,子组件和插槽都不可见 - 常见错觉:插槽里
{{ date | formatDate }}没报错 → 其实是全局过滤器在起作用,不是父组件“传下来”的
想让插槽内容用到某个格式化逻辑,该怎么做
别指望“传递过滤器”,要传递**数据或函数**。可行路径有三条:
- 把处理后的值传进去:
<my-card><view>{{ formattedDate }}</view></my-card>,其中formattedDate是父组件computed或data里已处理好的字符串 - 把原始值 + 工具函数一起传入:
<my-card :format-fn="formatDate"></my-card>,子组件接收后,在插槽作用域内调用(注意:需确保函数不依赖this或响应式上下文) - 改用作用域插槽(
v-slot):子组件暴露date数据,父组件用v-slot="{ date }"包裹并应用过滤器:<my-card v-slot="{ date }">{{ date | formatDate }}</my-card>—— 这才是真正“在父作用域执行过滤”的方式
作用域插槽里用过滤器的注意事项
这是唯一推荐的、语义清晰且可控的方式,但容易踩两个坑:
-
v-slot必须写在**子组件标签内部**,不能写在子组件模板里;否则就不是作用域插槽,而是普通插槽 - 如果用了 Vue 2(uni-app 2.x),
v-slot只支持写在组件上,不支持写在普通<view>上;写错位置会导致插槽不生效且无提示 - 过滤器仍需提前注册(全局或当前组件
filters),作用域插槽只是提供了父组件模板的执行环境,不自动带入过滤器
v-slot 暴露数据,再由父模板决定怎么渲染——这比试图让子组件“猜”父组件有哪些过滤器靠谱得多。


















