在Vue的createApp方法中,除了data(){}存放映射到页面的值、computed存放方法,还有一个属性template,这个属性说白了就是用来写HTML文件的。

由于Vue是挂载到DOM上的,因此我们可以通过template属性,把我们组件的HTML代码编写在里面,就可以不用多次书写HTML,可以用Vue一对多挂载上去

Vuejs一大特点就是组件式开发,组件式开发简单来说就是把一个网页各部分都拆分开来,当作一个个组件进行开发,组件就是一个个单独可用的功能块,然后通过复用组件达到代码的复用的效果。

根组件

我们目前写的这个网页可以看作是一个根组件,我们可以通过组件拆分的方式拆分我们的根组件,将其拆分为不同功能块的子组件。

首先我们创建一个components文件夹,用来存放组件,然后我们在里面创建一个App.js,这个文件用来存放我们的根组件,我们将我们index.html代码移动过来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
export default {
template: /*html*/ `
<section v-show="beforeBuy.length">
<h2>未购零食</h2>
<ul>
<li v-for="food in beforeBuy" :key="food.id">
<img :src="food.image">
<span>{{ food.name }}</span>
<input type="checkbox" v-model="food.purchased">
</li>
</ul>
</section>

<section v-show="afterBuy.length">
<h2>已购零食</h2>
<ul>
<li v-for="food in afterBuy" :key="food.id">
<img :src="food.image">
<span>{{ food.name }}</span>
<input type="checkbox" v-model="food.purchased">
</li>
</ul>
</section>
`,
data() {
return {
foods: [
{ id: 1, name: '原味鱿鱼丝', image: './images/原味鱿鱼丝.png', purchased: false },
{ id: 2, name: '辣味鱿鱼丝', image: './images/辣味鱿鱼丝.png', purchased: false },
{ id: 3, name: '炭烧味鱿鱼丝', image: './images/炭烧味鱿鱼丝.png', purchased: false }
]
}
},
computed: {
beforeBuy() {
return this.foods.filter(item => !item.purchased);
},
afterBuy() {
return this.foods.filter(item => item.purchased);
}
}
}

接着,我们需要修改index.html的内容

1
2
3
4
5
6
<div id="app"></div>

<script type="module">
import App from './components/App.js'
Vue.createApp(App).mount('#app');
</script>

这样我们就把index.html的内容搬迁到根组件了

拆组件

不过,这样搬迁显得组件似乎没什么作用,因此我们应该把根组件拆分成不同的组件,从而达到我们之前提及的效果。因此我们将我们当前根组件的内容先构建出一个组件,创建一个新的文件AppSections,将我们之前的内容搬迁过去,只留下空的computed,目前我们的代码大概是这样:

AppSections

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
export default {
template: /*html*/ `
<section v-show="beforeBuy.length">
<h2>未购零食</h2>
<ul>
<li v-for="food in beforeBuy" :key="food.id">
<img :src="food.image">
<span>{{ food.name }}</span>
<input type="checkbox" v-model="food.purchased">
</li>
</ul>
</section>

<section v-show="afterBuy.length">
<h2>已购零食</h2>
<ul>
<li v-for="food in afterBuy" :key="food.id">
<img :src="food.image">
<span>{{ food.name }}</span>
<input type="checkbox" v-model="food.purchased">
</li>
</ul>
</section>
`,
data() {
return {
foods: [
{ id: 1, name: '原味鱿鱼丝', image: './images/原味鱿鱼丝.png', purchased: false },
{ id: 2, name: '辣味鱿鱼丝', image: './images/辣味鱿鱼丝.png', purchased: false },
{ id: 3, name: '炭烧味鱿鱼丝', image: './images/炭烧味鱿鱼丝.png', purchased: false }
]
}
},
computed: {
beforeBuy() {
return this.foods.filter(item => !item.purchased);
},
afterBuy() {
return this.foods.filter(item => item.purchased);
}
}
}

App.js

1
2
3
4
5
import AppSections from "./AppSections";

export default {
template: ``
}

我们在引用子组件之前我们还需要注册组件,通过template同级的属性components属性,我们填入一个对象,在对象内填入组件的名字即可。注册组件后,我们就可以使用HTML标签的嵌入我们的子组件

1
2
3
4
5
6
7
8
import AppSections from "./AppSections.js";

export default {
components: { AppSections },
template: `
<app-sections></app-sections>
`
}

值得注意的是,由于HTML不区分大小写,我们坨锋命名的名字需要改写成小写和-连接。