Description
Sorry, Chinease only. I'll try to translate later.
What problem does this feature solve?
有时我希望在组件某区域渲染数据,它们都来自于data上比较深层的某一个属性,当数据量比较多时,直接使用文本插值的写法会比较繁琐,比如:
(以下为了精简代码,采用了pug、es6语法,并忽略Vue组件data必须为函数的要求)
The mustache interpolations of data in some deep props make the code cumbersome:
data.js
export default {
some: {
deep: {
props: {
a: 1,
b: 2,
},
},
},
};
my-page.vue
<template lang="pug">
div
p {{some.deep.props.a}}
p {{some.deep.props.b}}
</template>
<script>
import data from './data.js'
export default {
data,
}
</script>
我想到几种变通的做法:
I tried some solutions:
-
使用计算属性:Use computed properties:
my-page.vue
<template lang="pug"> div p {{props.a}} p {{props.b}} </template> <script> import data from './data.js' export default { data, computed: { props() { return this.some.deep.props; }, }, } </script>
这样做相对简单,但是总要为此去定义很多计算属性似乎也有些繁琐。
It is easy to use, but the computed properties become cumbersome. -
利用
v-for
指令来缩小作用域:Usev-for
directive to define a scoped variable:my-page.vue
<template lang="pug"> div template(v-for="props in [some.deep.props]") p(ref="a") {{props.a}} p(ref="b") {{props.b}} </template> <script> import data from './data.js' export default { data, } </script>
这是一个取巧的做法,但也有副作用:用
$refs
访问v-for
范围内的ref
引用会变成数组。
It almost works well, but have side-effect:$refs
in thev-for
scope will become an array. -
将数据渲染区域定义为子组件,子组件接受简化后的数据:Use child component:
data-view.vue
<template lang="pug"> div p {{props.a}} p {{props.b}} </template> <script> export default { props: ['props'], } </script>
my-page.vue
<template lang="pug"> div data-view(:props="some.deep.props") </template> <script> import data from './data.js' import DataView from './data-view.vue' export default { components: {DataView}, data, } </script>
子组件内部的写法能简化许多,但是整体花销仍然不小。一个额外的问题是,子组件多引入了一个可能原本并不必要的包装根元素。
Interpolations in child component become simple, but more children is also cumbersome. In addition, the child need a wrapper element as the component root, which was not needed before. -
利用子组件作用域插槽来封装一个通用的辅助组件:Use the scoped slot to make a reusable component:
sub-scope.vue
<template lang="pug"> div slot(:sub="data") </template> <script> export default { props: ['data'], } </script>
my-page.vue
<template lang="pug"> div sub-scope(:data="some.deep.props") template(slot-scope="scope") p {{scope.sub.a}} p {{scope.sub.b}} // or sub-scope(:data="some.deep.props") template(slot-scope="{sub}") p {{sub.a}} p {{sub.b}} </template> <script> import data from './data.js' import SubScope from './sub-scope.vue' export default { components: {SubScope}, data, } </script>
这也是取巧利用了子组件来改变访问作用域。可以复用看上去好像是一个优点,但实际使用还是比较繁琐,甚至代码看上去有些更乱了。与上一个方法同样存在的一个问题是,子组件引入了可能原本并不必要的包装根元素。
Only the interpolations look like simpler, but other codes become more complex.
What does the proposed API look like?
我感觉利用v-for
指令的办法很巧妙,就是多了一些副作用,虽然也不是非常严重的影响。
因此我希望能有一个指令,能够如同v-for
一样定义一个局部作用域变量,但又不会影响$refs
引用的表现。
I hope there is a directive can define scoped variables like v-for
, but will not affect the performance of $refs
.
div(v-scope="props of some.deep") {{props.a}}
// or
div(v-scope="(a, b) of some.deep.props") {{a}}, {{b}}
或者可以提供两种ref
元素访问接口:
Or the ref
API should be optimized:
$refs
仅用于访问指定引用名的第一项,类似于querySelector()
。$refs
should only be used for reference the first of elements with the sameref
value, likequerySelector()
.- 而
$groupedRefs
(我想也许还有更好一点的名字)则用于访问包含相同引用名的全部元素数组,类似于querySelectorAll()
。$groupedRefs
is used for reference the array of the elements with the sameref
value, likequerySelectorAll()
.