3

It's convenient to group data into nested object properties. By doing this, we don't have to collect properties from the data field into an entity for later use. As in the following example,

var demo = new Vue({
	el: '#demo',
        data: {
  	  level1: {
    	    level2: {
      	      level3_1: 'Hello',
              level3_2: 'world'
            }
          }
        }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

<div id="demo">
  <div class="person">
    <h3>{{ level1.level2.level3_1 }}</h3>
    <p>{{ level1.level2.level3_2 }}</p>
  </div>
</div>

However, it's really overkill having to type the "level1.level2" prefix in order to get to the level3_x field. It'll be very cumbersome if there're loads of level3 fields.

I wonder if there is any way that I can save the work for typing level1.level2 over and over again. Does the template have any syntax so that some section is under the scope of "level1.level2"? Does Vue provide any support so that in this case the prefix "level1.level2" is assumed?

2
  • 1
    Has anyone successfully answered your question yet? If not, please update your question with more details so we can help. If so, please remember to mark the answer that works best for you as accepted so the community can benefit from your feedback. Commented Sep 10, 2017 at 3:52
  • How about using computed ? Commented Jun 11, 2020 at 2:42

3 Answers 3

6

There are a couple of options.

1. Use v-for

Everything inside the v-for block is scoped to the level that you're iterating over. Do it like this:

var demo = new Vue({
	el: '#demo',
        data: {
  	  level1: {
    	    level2: {
      	      level3_1: 'Hello',
              level3_2: 'world'
            }
          }
        }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

<div id="demo">
  <div class="person">
    <template v-for="(l2prop, l2propName) in level1">
        <h3>{{ l2prop.level3_1 }}</h3>
        <p>{{ l2prop.level3_2 }}</p>
    </template>
  </div>
</div>

2. Use a component

Components get a subset of their parent's data, so they're automatically scoped. Do it like this:

Vue.component( "person", {
    props: ['data'],
    template: '<div class="person"><h3>{{ data.level3_1 }}</h3><p>{{ data.level3_2 }}</p></div>'
});

var demo = new Vue({
	el: '#demo',
        data: {
  	  level1: {
    	    level2: {
      	      level3_1: 'Hello',
              level3_2: 'world'
            }
          }
        }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

<div id="demo">
  <person v-bind:data="level1.level2"></person>
</div>

Sign up to request clarification or add additional context in comments.

3 Comments

It would be nice to be able to define/alias a child scope as in example #1 but for a single object, without a loop. You can do this in WPF by setting an element's DataContext property.
@xr280xr, I'm not aware of a way to do that. What advantage would that give you over using a child component?
Well this is an issue of convenience - we don't want to type or read long property paths in the bindings - but I think using a child component for only this reason, comes with more dev overhead (initial & maintenance) than productivity gained in many cases. A component is most useful when the content is reusable or you want to better define a logical boundary. But it can be that neither of those are true and you just want convenient naming so if you could say "let l1_2 point to `level1.level2' within this scope" it would be more simple and maybe more flexible.
0

The example of @jason-smith is almost right. v-for is used for arrays or lists. To make it work is necessary to put your object in list.

Following his example the better approach would be

var demo = new Vue({
  el: '#demo',
  data: {
    level1: {
      level2: {
        level3_1: 'Level 3_1',
        level3_2: 'Level 3_2'
      }
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
  <div class="person">
    <template v-for="level2Obj in [level1.level2]">
        <h3>{{ level2Obj.level3_1 }}</h3>
        <p>{{ level2Obj.level3_2 }}</p>
    </template>
  </div>
</div>

Comments

0

There are serval ways:

  1. Use a method that gets the same level

    methods:{ getLvl3: function(nr){ return this["level"+nr]["level"+nr]["level3_"+nr]; }

    {{ getLvl3(1) }}

  2. Iterate over with v-for v-for docu

example:

<div id="demo">
  <div class="person">
    <template v-for="(lvl2, key) in level1">
      <template v-for="(lvl3, key) in lvl2">
        <h3 v-if="key === 'level3_1'>{{ lvl3 }}</h3>
        <p v-if="key === 'level3_2'">{{ lvl3 }}</p>
      </template>
    </template>        
  </div>
</div>
  1. bind to variable that is defined outside of vue:

    var nested = { level1: { level2: { level3_1: 'Hello', level3_2: 'world' }}

and inside of vue component or instance:

data:{ 
  level2: nested.level1.level2,
}

<div id="demo">
  <div class="person">
    <h3>{{ level2.level3_1 }}</h3>
    <p>{{ level2.level3_2 }}</p>
  </div>
</div>

1 Comment

I don't recommend using a method for this, since it breaks the reactivity pattern. Doing that very much will get costly in terms of un-needed recalculations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.