Skip to content

Commit 9216e43

Browse files
Move conditional rendering and list rendering (#33)
* feat: moved conditional rendering doc * feat: finished list migration * Fixed toggleLoginType method * fix: renamed `object` to `myObject` * fix: fix data to be a function and nested example
1 parent 98634cf commit 9216e43

File tree

12 files changed

+732
-2
lines changed

12 files changed

+732
-2
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<template>
2+
<div id="no-key-example" class="demo">
3+
<div>
4+
<template v-if="loginType === 'username'">
5+
<label>Username</label>
6+
<input placeholder="Enter your username" />
7+
</template>
8+
<template v-else>
9+
<label>Email</label>
10+
<input placeholder="Enter your email address" />
11+
</template>
12+
</div>
13+
<button @click="toggleLoginType">Toggle login type</button>
14+
</div>
15+
</template>
16+
17+
<script>
18+
export default {
19+
data() {
20+
return {
21+
loginType: 'username'
22+
}
23+
},
24+
methods: {
25+
toggleLoginType() {
26+
this.loginType = this.loginType === 'username' ? 'email' : 'username'
27+
}
28+
}
29+
}
30+
</script>
31+
32+
<style lang="scss" scoped></style>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<template>
2+
<div id="no-key-example" class="demo">
3+
<div>
4+
<template v-if="loginType === 'username'">
5+
<label>Username</label>
6+
<input placeholder="Enter your username" key="username-input" />
7+
</template>
8+
<template v-else>
9+
<label>Email</label>
10+
<input placeholder="Enter your email address" key="email-input" />
11+
</template>
12+
</div>
13+
<button @click="toggleLoginType">Toggle login type</button>
14+
</div>
15+
</template>
16+
17+
<script>
18+
export default {
19+
data() {
20+
return {
21+
loginType: 'username'
22+
}
23+
},
24+
methods: {
25+
toggleLoginType() {
26+
this.loginType = this.loginType === 'username' ? 'email' : 'username'
27+
}
28+
}
29+
}
30+
</script>
31+
32+
<style lang="scss" scoped></style>

src/.vuepress/components/list-1.vue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<template>
2+
<ul id="example-1" class="demo">
3+
<li v-for="item in items">
4+
{{ item.message }}
5+
</li>
6+
</ul>
7+
</template>
8+
9+
<script>
10+
export default {
11+
data() {
12+
return {
13+
items: [{ message: 'Foo' }, { message: 'Bar' }]
14+
}
15+
}
16+
}
17+
</script>

src/.vuepress/components/list-2.vue

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<template>
2+
<ul id="example-2" class="demo">
3+
<li v-for="(item, index) in items">
4+
{{ parentMessage }} - {{ index }} - {{ item.message }}
5+
</li>
6+
</ul>
7+
</template>
8+
9+
<script>
10+
export default {
11+
data() {
12+
return {
13+
parentMessage: 'Parent',
14+
items: [{ message: 'Foo' }, { message: 'Bar' }]
15+
}
16+
}
17+
}
18+
</script>

src/.vuepress/components/list-3.vue

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<template>
2+
<ul id="v-for-object" class="demo">
3+
<li v-for="value in myObject">
4+
{{ value }}
5+
</li>
6+
</ul>
7+
</template>
8+
9+
<script>
10+
export default {
11+
data() {
12+
return {
13+
myObject: {
14+
title: 'How to do lists in Vue',
15+
author: 'Jane Doe',
16+
publishedAt: '2016-04-10'
17+
}
18+
}
19+
}
20+
}
21+
</script>

src/.vuepress/components/list-4.vue

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<template>
2+
<ul id="v-for-object" class="demo">
3+
<li v-for="(value, name) in myObject">{{ name }}: {{ value }}</li>
4+
</ul>
5+
</template>
6+
7+
<script>
8+
export default {
9+
data() {
10+
return {
11+
myObject: {
12+
title: 'How to do lists in Vue',
13+
author: 'Jane Doe',
14+
publishedAt: '2016-04-10'
15+
}
16+
}
17+
}
18+
}
19+
</script>
20+
21+
<style lang="scss" scoped></style>

src/.vuepress/components/list-5.vue

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<template>
2+
<ul id="v-for-object" class="demo">
3+
<li v-for="(value, name, index) in myObject">
4+
{{ index }}. {{ name }}: {{ value }}
5+
</li>
6+
</ul>
7+
</template>
8+
9+
<script>
10+
export default {
11+
data() {
12+
return {
13+
myObject: {
14+
title: 'How to do lists in Vue',
15+
author: 'Jane Doe',
16+
publishedAt: '2016-04-10'
17+
}
18+
}
19+
}
20+
}
21+
</script>
22+
23+
<style lang="scss" scoped></style>

src/.vuepress/components/list-6.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<template>
2+
<div id="range" class="demo">
3+
<span v-for="n in 10">{{ n }} </span>
4+
</div>
5+
</template>

src/.vuepress/components/list-7.vue

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<template>
2+
<div id="todo-list-example">
3+
<form v-on:submit.prevent="addNewTodo">
4+
<label for="new-todo">Add a todo</label>
5+
<input
6+
v-model="newTodoText"
7+
id="new-todo"
8+
placeholder="E.g. Feed the cat"
9+
/>
10+
<button>Add</button>
11+
</form>
12+
<ul>
13+
<li v-for="(todo, index) in todos" :key="todo.id">
14+
{{ todo.title }}
15+
<button v-on:click="todos.splice(index, 1)">Remove</button>
16+
</li>
17+
</ul>
18+
</div>
19+
</template>
20+
21+
<script>
22+
export default {
23+
data() {
24+
return {
25+
newTodoText: '',
26+
todos: [
27+
{
28+
id: 1,
29+
title: 'Do the dishes'
30+
},
31+
{
32+
id: 2,
33+
title: 'Take out the trash'
34+
},
35+
{
36+
id: 3,
37+
title: 'Mow the lawn'
38+
}
39+
],
40+
nextTodoId: 4
41+
}
42+
},
43+
methods: {
44+
addNewTodo() {
45+
this.todos.push({
46+
id: this.nextTodoId++,
47+
title: this.newTodoText
48+
})
49+
this.newTodoText = ''
50+
}
51+
}
52+
}
53+
</script>

src/.vuepress/config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ module.exports = {
3636
'template-syntax',
3737
// 'computed',
3838
// 'class-and-style',
39-
// 'conditional',
40-
// 'list'
39+
'conditional',
40+
'list'
4141
// 'events'
4242
]
4343
}

src/guide/conditional.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Conditional Rendering
2+
3+
<div class="vueschool"><a href="https://vueschool.io/lessons/vuejs-conditionals?friend=vuejs" target="_blank" rel="sponsored noopener" title="Learn how conditional rendering works with Vue School">Learn how conditional rendering works with a free lesson on Vue School</a></div>
4+
5+
## `v-if`
6+
7+
The directive `v-if` is used to conditionally render a block. The block will only be rendered if the directive's expression returns a truthy value.
8+
9+
```html
10+
<h1 v-if="awesome">Vue is awesome!</h1>
11+
```
12+
13+
It is also possible to add an "else block" with `v-else`:
14+
15+
```html
16+
<h1 v-if="awesome">Vue is awesome!</h1>
17+
<h1 v-else>Oh no 😢</h1>
18+
```
19+
20+
### Conditional Groups with `v-if` on `<template>`
21+
22+
Because `v-if` is a directive, it has to be attached to a single element. But what if we want to toggle more than one element? In this case we can use `v-if` on a `<template>` element, which serves as an invisible wrapper. The final rendered result will not include the `<template>` element.
23+
24+
```html
25+
<template v-if="ok">
26+
<h1>Title</h1>
27+
<p>Paragraph 1</p>
28+
<p>Paragraph 2</p>
29+
</template>
30+
```
31+
32+
### `v-else`
33+
34+
You can use the `v-else` directive to indicate an "else block" for `v-if`:
35+
36+
```html
37+
<div v-if="Math.random() > 0.5">
38+
Now you see me
39+
</div>
40+
<div v-else>
41+
Now you don't
42+
</div>
43+
```
44+
45+
A `v-else` element must immediately follow a `v-if` or a `v-else-if` element - otherwise it will not be recognized.
46+
47+
### `v-else-if`
48+
49+
The `v-else-if`, as the name suggests, serves as an "else if block" for `v-if`. It can also be chained multiple times:
50+
51+
```html
52+
<div v-if="type === 'A'">
53+
A
54+
</div>
55+
<div v-else-if="type === 'B'">
56+
B
57+
</div>
58+
<div v-else-if="type === 'C'">
59+
C
60+
</div>
61+
<div v-else>
62+
Not A/B/C
63+
</div>
64+
```
65+
66+
Similar to `v-else`, a `v-else-if` element must immediately follow a `v-if` or a `v-else-if` element.
67+
68+
### Controlling Reusable Elements with `key`
69+
70+
Vue tries to render elements as efficiently as possible, often re-using them instead of rendering from scratch. Beyond helping make Vue very fast, this can have some useful advantages. For example, if you allow users to toggle between multiple login types:
71+
72+
```html
73+
<template v-if="loginType === 'username'">
74+
<label>Username</label>
75+
<input placeholder="Enter your username" />
76+
</template>
77+
<template v-else>
78+
<label>Email</label>
79+
<input placeholder="Enter your email address" />
80+
</template>
81+
```
82+
83+
Then switching the `loginType` in the code above will not erase what the user has already entered. Since both templates use the same elements, the `<input>` is not replaced - just its `placeholder`.
84+
85+
Check it out for yourself by entering some text in the input, then pressing the toggle button:
86+
87+
<conditional-1 />
88+
89+
This isn't always desirable though, so Vue offers a way for you to say, "These two elements are completely separate - don't re-use them." Add a `key` attribute with unique values:
90+
91+
```html
92+
<template v-if="loginType === 'username'">
93+
<label>Username</label>
94+
<input placeholder="Enter your username" key="username-input" />
95+
</template>
96+
<template v-else>
97+
<label>Email</label>
98+
<input placeholder="Enter your email address" key="email-input" />
99+
</template>
100+
```
101+
102+
Now those inputs will be rendered from scratch each time you toggle. See for yourself:
103+
104+
<conditional-2 />
105+
106+
Note that the `<label>` elements are still efficiently re-used, because they don't have `key` attributes.
107+
108+
## `v-show`
109+
110+
Another option for conditionally displaying an element is the `v-show` directive. The usage is largely the same:
111+
112+
```html
113+
<h1 v-show="ok">Hello!</h1>
114+
```
115+
116+
The difference is that an element with `v-show` will always be rendered and remain in the DOM; `v-show` only toggles the `display` CSS property of the element.
117+
118+
::: tip
119+
Note that `v-show` doesn't support the ::: v-pre `<template>` ::: element, nor does it work with `v-else`.</p>
120+
:::
121+
122+
## `v-if` vs `v-show`
123+
124+
`v-if` is "real" conditional rendering because it ensures that event listeners and child components inside the conditional block are properly destroyed and re-created during toggles.
125+
126+
`v-if` is also **lazy**: if the condition is false on initial render, it will not do anything - the conditional block won't be rendered until the condition becomes true for the first time.
127+
128+
In comparison, `v-show` is much simpler - the element is always rendered regardless of initial condition, with CSS-based toggling.
129+
130+
Generally speaking, `v-if` has higher toggle costs while `v-show` has higher initial render costs. So prefer `v-show` if you need to toggle something very often, and prefer `v-if` if the condition is unlikely to change at runtime.
131+
132+
## `v-if` with `v-for`
133+
134+
::: tip
135+
Using `v-if` and `v-for` together is **not recommended**. See the [style guide](TODO:/v2/style-guide/#Avoid-v-if-with-v-for-essential) for further information.
136+
:::
137+
138+
When used together with `v-if`, `v-for` has a higher priority than `v-if`. See the [list rendering guide](list#v-for-with-v-if) for details.

0 commit comments

Comments
 (0)