We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
最近,使用 Vue 开发组件时遇到了这样一个问题:开发的组件所能够自定义的 props 比较多,导致使用该组件时需要传入太多属性,数据、样式控制什么的属性都在一起了,看起来很不美观,像下面这样:
props
<some-component title="我是标题" :pos="[0, 0]" :size="[500, 400]" :radius="[0, 0.5]" :borderWidth="2" :borderColor="'#fff'" :data="testData" />
虽然看起来可能还好,但是实际使用时可以自定义的属性是不止这些的,这样使用起来就很不美观了。于是就有了这样一个想法:定义一个类似于 React 中常写的 theme 组件,将一些非数据相关的 props 定义到 theme 组件上,theme 组件再自动将 props 透传给其他组件使用即可。theme 组件使用起来像这样:
React
theme
<theme :pos="[0, 0]" :size="[500, 400]" :radius="[0, 0.5]" :borderWidth="2" :borderColor="'#fff'" > <some-component title="我是标题":data="testData" /> </thmem>
在 React 中,开发这样一个高阶组件 theme 是很简单的。但是在 vue 中如何开发 theme 组件以达到上面设想的使用效果?通过翻阅 Vue 的文档,发现借助 $slots 和 render 函数可以做到。
vue
Vue
$slots
render
export default { name: 'theme', render(h) { const theme = this.$attrs // 通过 $attrs 可以拿到使用该组件时定义的 props,而无需声明有哪些 props const merge = vNode => { if (!vNode.tag) { return } if (vNode.componentOptions) { let props = vNode.componentOptions.propsData props = Object.assign({}, theme, props) vNode.componentOptions.propsData = props } else { if (!vNode.data) { return } let attrs = vNode.data.attrs || {} attrs = Object.assign({}, theme, attrs) vNode.data.attrs = attrs } } this.$slots.default.map(vNode => merge(vNode)) Object.keys(this.$attrs).forEach(key => { this.$attrs[key] = null }) return this.$slots.default[0] // 直接返回,无需额外渲染 } }
如此便达到了这样的使用效果:
很显然 theme 组件是没有渲染的,它所做的也只不过是透传 props 给其它组件而已,称之为 无渲染组件。
无渲染组件
slot-scope
在 Vue文档 中提到了 slot-scope 可以使用作用域插槽变得更干净。那么结合 theme 组件的经验,可以写出这样一款 axios 组件。
axios
Vue.component('s-axios', { props: ['url'], data() { return { loading: true, response: null } }, created() { axios.get(this.url) .then(response => { this.loading = false this.response = response }) }, render() { return this.$scopedSlots.default({ loading: this.loading, response: this.response }) } })
使用起来也很方便:
<div id="app"> <s-axios url="https://api.github.com/orgs/reactjs/repos"> <div slot-scope="{ loading, response }"> <div v-if="loading">loading</div> <div v-else>响应数据为:${{ response.data }}</div> </div> </s-axios> </div>
可以点击查看在线Demo。
通过 $slots、$scopedSlots结合 render可以创造很多好玩的组件,比如本篇文章中说到的 无渲染组件 ,关键就在于使用者怎么想。
$scopedSlots
The text was updated successfully, but these errors were encountered:
这个就是类似React里的render props吧
Sorry, something went wrong.
@riyueweiyi 是的【哈哈】
传多个参数用v-bind="data"不就可以了吗?
@kaysonli 可以,还是看个人开发时想怎么用。
No branches or pull requests
Vue 技巧:无渲染组件
最近,使用 Vue 开发组件时遇到了这样一个问题:开发的组件所能够自定义的
props
比较多,导致使用该组件时需要传入太多属性,数据、样式控制什么的属性都在一起了,看起来很不美观,像下面这样:虽然看起来可能还好,但是实际使用时可以自定义的属性是不止这些的,这样使用起来就很不美观了。于是就有了这样一个想法:定义一个类似于
React
中常写的theme
组件,将一些非数据相关的props
定义到theme
组件上,theme
组件再自动将props
透传给其他组件使用即可。theme
组件使用起来像这样:开发
theme
组件在
React
中,开发这样一个高阶组件theme
是很简单的。但是在vue
中如何开发theme
组件以达到上面设想的使用效果?通过翻阅Vue
的文档,发现借助$slots
和render
函数可以做到。如此便达到了这样的使用效果:
很显然
theme
组件是没有渲染的,它所做的也只不过是透传 props 给其它组件而已,称之为无渲染组件
。slot-scope
在 Vue文档 中提到了
slot-scope
可以使用作用域插槽变得更干净。那么结合theme
组件的经验,可以写出这样一款axios
组件。使用起来也很方便:
可以点击查看在线Demo。
总结
通过
$slots
、$scopedSlots
结合render
可以创造很多好玩的组件,比如本篇文章中说到的 无渲染组件 ,关键就在于使用者怎么想。The text was updated successfully, but these errors were encountered: