[译]: Vue.js 函数式组件:what, why & when?

原文:https://medium.com/js-dojo/vue-js-functional-components-what-why-and-when-439cfaa08713

要义:如果你的组件不需要状态化,将其转换为一个 函数式组件(functional component) 可提高 70% 的渲染性能

What - 何为函数式组件?

functional component (别跟 Vue 的 render function 搞混) 是一个不持有状态也没有实例的组件。

说白了,这就意味着这种组件不支持反应式,并且不能用 this 关键字引用到自身。

基于模板的函数式组件

基于 render 函数的函数式组件

访问组件属性

你肯定会疑惑,离开了状态或实例,怎么引用诸如 data 或 methods 等东西。幸运的是,Vue 在 render() 中提供了一个 context 参数,该参数是一个有下列属性的对象:

  • props:提供所有 prop 的对象

  • children:VNode 子节点的数组

  • slots:一个函数,返回了包含所有插槽的对象

  • scopedSlots:(2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。

  • data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件

  • parent:对父组件的引用

  • listeners:(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。

  • injections:(2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的 property。

访问这个 context 参数相当简单。举例来说,如果想获得属性,这样就可以:

在模板中访问上下文

在 render 函数中访问上下文

???? 函数式组件和属性:

在一个函数式组件中,实际上你不用再显式声明一遍可接收的 props(译注:大于 2.3.0 版本)。然而,一旦你显式声明了 props,这些属性就将依此校验。我个人仍推崇这样做,这样就能指定其类型、required、默认值,或自定义校验器等。

Why - 函数式组件为何有趣?

函数式组件让对组件的访问有点麻烦了,也带来了一些复杂性,那还为什么要自找麻烦呢?

快!

因为函数式组件没有状态,也就不需要针对 Vue 反应式系统等额外的初始化了。

虽然仍会对新传入的 props 等做出反应,但对于组件自身,并不知晓其数据何时改变,因为其并不维护自己的状态。

对于指标爱好者,我也做了一个性能测试:分别用状态化组件和函数式组件渲染 1000 条长的列表,两者用时分别是 140ms 及 40ms 。

When - 何时该用函数式组件?

函数式组件也不是万金油。说到底,使用一个 JavaScript 框架来构建应用图的不就是更好的反应性嘛。在这一点上对于 Vue 来说,其反应式系统仍是不可替代的。

然而仍有一些函数式组件能大展拳脚的用例:

  • 显式逻辑特别简单的组件,也叫“哑(dumb)”组件。比如按钮、卡片、标签甚至纯静态的“关于”页面等。

  • 一个被用来包裹模板置标或丰富其他组件基础功能的高阶组件。

  • 每当你发现自己陷入了一个循环渲染 (v-for),其遍历对象往往就适用函数式组件

派生值

在特别的场景中,我还是发现了一个小问题。当使用 <template> 标签,并且从 props 中访问一个数据时,有时需要在模板中渲染加工过的数据。

使用标准的 Vue 组件时,用 methods 也好 computed 也罢,这都易如反掌。但对于函数式组件,这两个是不可用的。

也不是没有辙。

就拿经典的 fullName 例子来说,在一个函数式 <template> 中,可以通过直接在组件定义中提供一个方法,并在之后使用 Vue 提供的 $options 属性来调用我们自定义的方法,以达到目的:

函数式组件中的“计算属性”

其他问题

社区中有人发现,当嵌套有着 scoped slots 的函数式组件时,表现并不正常 https://github.com/vuejs/vue-loader/issues/1136

总结

如果你关注性能,或正在开发大型应用,可以考虑使用函数式组件。微不足道的学习曲线将带来巨大的性能收益。

扩展阅读



--End--

查看更多前端好文
请搜索 fewelife 关注公众号

转载请注明出处

正在执行任务: npm run test:jest &gt; origin@0.1.1 test:jest &gt; VUE_APP_SSO_ENV=test jest Browserslist: caniuse-lite is outdated. Please run: npx update-browserslist-db@latest Why you should do it regularly: https://github.com/browserslist/update-db#readme Browserslist: caniuse-lite is outdated. Please run: npx update-browserslist-db@latest Why you should do it regularly: https://github.com/browserslist/update-db#readme Browserslist: caniuse-lite is outdated. Please run: npx update-browserslist-db@latest Why you should do it regularly: https://github.com/browserslist/update-db#readme Browserslist: caniuse-lite is outdated. Please run: npx update-browserslist-db@latest Why you should do it regularly: https://github.com/browserslist/update-db#readme FAIL tests/integration/kpiManage/editKpi/EditStandard.spec.ts ● Test suite failed to run Jest encountered an unexpected token Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax. Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration. By default &quot;node_modules&quot; folder is ignored by transformers. Here&#39;s what you can do: &bull; If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it. &bull; If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript &bull; To have some of your &quot;node_modules&quot; files transformed, you can specify a custom &quot;transformIgnorePatterns&quot; in your config. &bull; If you need a custom transformation specify a &quot;transform&quot; option in your config. &bull; If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the &quot;moduleNameMapper&quot; config option. You&#39;ll find more details and examples of these config options in the docs: https://jestjs.io/docs/configuration For information about custom transformations, see: https://jestjs.io/docs/code-transformation Details: SyntaxError: Unexpected token (25:23) at Parser.pp$4.raise (node_modules/vue-template-es2015-compiler/buble.js:2757:13) at Parser.pp.unexpected (node_modules/vue-template-es2015-compiler/buble.js:647:8) at Parser.pp$3.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:2196:10) at Parser.&lt;anonymous&gt; (node_modules/vue-template-es2015-compiler/buble.js:6003:24) at Parser.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:6129:31) at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2047:19) at Parser.pp$3.parseMaybeUnary (node_modules/vue-template-es2015-compiler/buble.js:2024:17) at Parser.pp$3.parseExprOps (node_modules/vue-template-es2015-compiler/buble.js:1966:19) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1949:19) at Parser.pp$3.parseMaybeAssign (node_modules/vue-template-es2015-compiler/buble.js:1925:19) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1954:28) at Parser.pp$3.parseMaybeAssign (node_modules/vue-template-es2015-compiler/buble.js:1925:19) at Parser.pp$3.parseExprList (node_modules/vue-template-es2015-compiler/buble.js:2663:20) at Parser.pp$3.parseSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2075:29) at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2050:21) at Parser.pp$3.parseMaybeUnary (node_modules/vue-template-es2015-compiler/buble.js:2024:17) at Parser.pp$3.parseExprOp (node_modules/vue-template-es2015-compiler/buble.js:1985:41) at Parser.pp$3.parseExprOps (node_modules/vue-template-es2015-compiler/buble.js:1968:91) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1949:19) at Parser.pp$3.parseMaybeAssign (node_modules/vue-template-es2015-compiler/buble.js:1925:19) at Parser.pp$3.parseExprList (node_modules/vue-template-es2015-compiler/buble.js:2663:20) at Parser.pp$3.parseSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2075:29) at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2050:21) at Parser.pp$3.parseMaybeUnary (node_modules/vue-template-es2015-compiler/buble.js:2024:17) at Parser.pp$3.parseExprOps (node_modules/vue-template-es2015-compiler/buble.js:1966:19) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1949:19) at Parser.pp$3.parseMaybeAssign (node_modules/vue-template-es2015-compiler/buble.js:1925:19) at Parser.pp$3.parseExprList (node_modules/vue-template-es2015-compiler/buble.js:2663:20) at Parser.pp$3.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:2175:26) at Parser.&lt;anonymous&gt; (node_modules/vue-template-es2015-compiler/buble.js:6003:24) at Parser.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:6129:31) at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2047:19) at Parser.pp$3.parseMaybeUnary (node_modules/vue-template-es2015-compiler/buble.js:2024:17) at Parser.pp$3.parseExprOps (node_modules/vue-template-es2015-compiler/buble.js:1966:19) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1949:19) at Parser.pp$3.parseMaybeAssign (node_modules/vue-template-es2015-compiler/buble.js:1925:19) at Parser.pp$3.parseExpression (node_modules/vue-template-es2015-compiler/buble.js:1896:19) at Parser.pp$1.parseReturnStatement (node_modules/vue-template-es2015-compiler/buble.js:946:31) at Parser.pp$1.parseStatement (node_modules/vue-template-es2015-compiler/buble.js:781:35) at Parser.parseStatement (node_modules/vue-template-es2015-compiler/buble.js:6116:31) at Parser.pp$1.parseBlock (node_modules/vue-template-es2015-compiler/buble.js:1112:23) at Parser.pp$3.parseFunctionBody (node_modules/vue-template-es2015-compiler/buble.js:2600:22) at Parser.pp$1.parseFunction (node_modules/vue-template-es2015-compiler/buble.js:1219:8) at Parser.pp$3.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:2184:17) at Parser.&lt;anonymous&gt; (node_modules/vue-template-es2015-compiler/buble.js:6003:24) at Parser.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:6129:31) at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2047:19) at Parser.pp$3.parseMaybeUnary (node_modules/vue-template-es2015-compiler/buble.js:2024:17) at Parser.pp$3.parseExprOps (node_modules/vue-template-es2015-compiler/buble.js:1966:19) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1949:19) FAIL tests/integration/kpiManage/createKpi/CreateStandard.spec.ts ● Test suite failed to run Jest encountered an unexpected token Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax. Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration. By default &quot;node_modules&quot; folder is ignored by transformers. Here&#39;s what you can do: &bull; If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it. &bull; If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript &bull; To have some of your &quot;node_modules&quot; files transformed, you can specify a custom &quot;transformIgnorePatterns&quot; in your config. &bull; If you need a custom transformation specify a &quot;transform&quot; option in your config. &bull; If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the &quot;moduleNameMapper&quot; config option. You&#39;ll find more details and examples of these config options in the docs: https://jestjs.io/docs/configuration For information about custom transformations, see: https://jestjs.io/docs/code-transformation Details: SyntaxError: Unexpected token (25:23) at Parser.pp$4.raise (node_modules/vue-template-es2015-compiler/buble.js:2757:13) at Parser.pp.unexpected (node_modules/vue-template-es2015-compiler/buble.js:647:8) at Parser.pp$3.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:2196:10) at Parser.&lt;anonymous&gt; (node_modules/vue-template-es2015-compiler/buble.js:6003:24) at Parser.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:6129:31) at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2047:19) at Parser.pp$3.parseMaybeUnary (node_modules/vue-template-es2015-compiler/buble.js:2024:17) at Parser.pp$3.parseExprOps (node_modules/vue-template-es2015-compiler/buble.js:1966:19) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1949:19) at Parser.pp$3.parseMaybeAssign (node_modules/vue-template-es2015-compiler/buble.js:1925:19) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1954:28) at Parser.pp$3.parseMaybeAssign (node_modules/vue-template-es2015-compiler/buble.js:1925:19) at Parser.pp$3.parseExprList (node_modules/vue-template-es2015-compiler/buble.js:2663:20) at Parser.pp$3.parseSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2075:29) at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2050:21) at Parser.pp$3.parseMaybeUnary (node_modules/vue-template-es2015-compiler/buble.js:2024:17) at Parser.pp$3.parseExprOp (node_modules/vue-template-es2015-compiler/buble.js:1985:41) at Parser.pp$3.parseExprOps (node_modules/vue-template-es2015-compiler/buble.js:1968:91) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1949:19) at Parser.pp$3.parseMaybeAssign (node_modules/vue-template-es2015-compiler/buble.js:1925:19) at Parser.pp$3.parseExprList (node_modules/vue-template-es2015-compiler/buble.js:2663:20) at Parser.pp$3.parseSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2075:29) at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2050:21) at Parser.pp$3.parseMaybeUnary (node_modules/vue-template-es2015-compiler/buble.js:2024:17) at Parser.pp$3.parseExprOps (node_modules/vue-template-es2015-compiler/buble.js:1966:19) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1949:19) at Parser.pp$3.parseMaybeAssign (node_modules/vue-template-es2015-compiler/buble.js:1925:19) at Parser.pp$3.parseExprList (node_modules/vue-template-es2015-compiler/buble.js:2663:20) at Parser.pp$3.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:2175:26) at Parser.&lt;anonymous&gt; (node_modules/vue-template-es2015-compiler/buble.js:6003:24) at Parser.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:6129:31) at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2047:19) at Parser.pp$3.parseMaybeUnary (node_modules/vue-template-es2015-compiler/buble.js:2024:17) at Parser.pp$3.parseExprOps (node_modules/vue-template-es2015-compiler/buble.js:1966:19) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1949:19) at Parser.pp$3.parseMaybeAssign (node_modules/vue-template-es2015-compiler/buble.js:1925:19) at Parser.pp$3.parseExpression (node_modules/vue-template-es2015-compiler/buble.js:1896:19) at Parser.pp$1.parseReturnStatement (node_modules/vue-template-es2015-compiler/buble.js:946:31) at Parser.pp$1.parseStatement (node_modules/vue-template-es2015-compiler/buble.js:781:35) at Parser.parseStatement (node_modules/vue-template-es2015-compiler/buble.js:6116:31) at Parser.pp$1.parseBlock (node_modules/vue-template-es2015-compiler/buble.js:1112:23) at Parser.pp$3.parseFunctionBody (node_modules/vue-template-es2015-compiler/buble.js:2600:22) at Parser.pp$1.parseFunction (node_modules/vue-template-es2015-compiler/buble.js:1219:8) at Parser.pp$3.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:2184:17) at Parser.&lt;anonymous&gt; (node_modules/vue-template-es2015-compiler/buble.js:6003:24) at Parser.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:6129:31) at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2047:19) at Parser.pp$3.parseMaybeUnary (node_modules/vue-template-es2015-compiler/buble.js:2024:17) at Parser.pp$3.parseExprOps (node_modules/vue-template-es2015-compiler/buble.js:1966:19) at Parser.pp$3.parseMaybeConditional (node_modules/vue-template-es2015-compiler/buble.js:1949:19) Test Suites: 2 failed, 2 total Tests: 0 total Snapshots: 0 total Time: 9.502 s Ran all test suites. npm error Lifecycle script `test:jest` failed with error: npm error code 1 npm error path /Users/tianyinfeng/Desktop/自动化测试/data_metrics_store/packages/origin npm error workspace origin@0.1.1 npm error location /Users/tianyinfeng/Desktop/自动化测试/data_metrics_store/packages/origin npm error command failed npm error command sh -c VUE_APP_SSO_ENV=test jest * 终端进程&ldquo;/bin/zsh &#39;-l&#39;, &#39;-c&#39;, &#39;npm run test:jest&#39;&rdquo;已终止,退出代码: 1。 * 终端将被任务重用,按任意键关闭。 执行test时,这是什么问题,怎么解决
08-07
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值