10000 hope to have a way to set scope of variable · Issue #6913 · vuejs/vue · GitHub
[go: up one dir, main page]

Skip to content
hope to have a way to set scope of variable #6913
Closed
@caikan

Description

@caikan

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:

  1. 使用计算属性: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.

  2. 利用v-for指令来缩小作用域:Use v-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 the v-for scope will become an array.

  3. 将数据渲染区域定义为子组件,子组件接受简化后的数据: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.

  4. 利用子组件作用域插槽来封装一个通用的辅助组件: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 same ref value, like querySelector().
  • $groupedRefs(我想也许还有更好一点的名字)则用于访问包含相同引用名的全部元素数组,类似于querySelectorAll()$groupedRefs is used for reference the array of the elements with the same ref value, like querySelectorAll().

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0