前言
这又是一篇很基础很基础的文章。(因为我菜鸡呀.估计大佬们都去折腾算法分析什么的,只有我这个菜鸡还在天天搬砖,太难了。
本篇文章主要讲述如何用 Vue Components 减少重复代码量。
需求
博客的友链页是由一个表格构成的:
name | url | description |
---|---|---|
张三 | https://zhangsan.com | 张三的挖坑日记 |
李四 | https://lisi.com | 李四的网络日志 |
不行,这太简陋了。如何编写一个更好的友链页呢?
实现
那么我们就用 Bootstrap 的卡片来实现一个卡片式的友链页吧。
实现1 不用 Vue
下面我们用 Bootstrap 的卡片实现一个友链卡片。
<!--为了使代码在这个例子中更加简洁,我暂且用 style 规定了一下卡片的宽度。-->
<div class="card" style="width:20rem;">
<div class="card-body">
<!-- 标题 -->
<p class="h4">张三</p>
<!-- 描述 -->
<p>张三的挖坑日记</p>
</div>
<div class="card-footer">
<!-- 链接 -->
<a href="https://zhangsan.com">https://zhangsan.com</a>
</div>
</div>
实现效果如下:
张三
张三的挖坑日记
这个做法有两个缺点:
- 如果我们来了一位新的朋友,需要再次复制粘贴,这很不合理。
- 如果我们需要修改卡片的样式,我们需要手动修改 n 次(n=朋友的个数)。
实现2 Vue App
引入 Vue,利用v-for
我们可以提高代码的复用性。
先定义一个 Vue App,然后把朋友们以数组的形式录入 data
中。
var app = new Vue({
el: '#app',
data: {
friends: [
{
name: "张三",
description: "张三的挖坑日记",
url: "https://zhangsan.com/"
},
{
name: "李四",
description: "李四的网络日志",
url: "https://lisi.com/"
}
]
}
})<>
然后我们用v-for
遍历一下friends
这个元素。
<div id="app">
<!-- 在这里用 v-for 遍历数组内容,其实它是一个 foreach -->
<div class="card" style="width:20rem;" v-for="friend in friends">
<div class="card-body">
<!-- 标题 -->
<p class="h4">{{friend.name}}</p>
<!-- 描述 -->
<p>{{friend.description}}</p>
</div>
<div class="card-footer">
<!-- 链接,注意 这个地方要用v-bind:href -->
<a v- bind:href="friend.url">{{friend.url}}</a>
<!-- 关于这一点请参见 https://cn.vuejs.org/v2/guide/syntax.html#Attribute -->
<!-- v-bind 也可以缩写为 `:url="friend.url"` 。 -->
</div>
</div>
</div>
这样可以复用卡片代码,并且修改样式也很方便了。
但这个代码还是不完美:
- 首先,如果你有个新的朋友,却需要修改 Vue App 的
data
属性。为了 HTML 内容而修改 Javascript 是很不合理的。我们需要给 Javascript 和 HTML 解藕。 - 不过为这一个页面开一个 Vue App 是不是有点小题大作呢? 而且更重要的一点是,一山不容二虎,嵌套 Vue App 会导致奇怪的 Bug。
(禁止套娃
实现3 Vue 组件
How can we do better?
如果有这么一种写法,就比较完美了:
<friend description="张三的挖坑日记" url="https://zhangsan.com">张三</friend>
<friend description="李四的网络日志" url="https://lisi.com">李四</friend>
很幸运的是,Vue.js 提供这种功能。
我们可以定义一个 Vue Component。这里要引入两样东西:
Vue.component('friend',{
// 注意一定要在这里定义 props,否则会提示 not defined 的问题。
props:['url','description'],
template: `
<div class="card" style="width:20rem;">
<div class="card-body">
<!-- 标题,这里用了slot,目的是在这里插入“<friend>这里</friend>”的内容。 -->
<p class="h4"><slot></slot></p>
<!-- 描述,这里就是对“<friend description="这里"...”内容的提取。 -->
<p>{{ description }}</p>
</div>
<div class="card-footer">
<!-- 链接,同理,这个我就不用解释了。注意这里也要用 v-bind -->
<a v-bind:href="url">{{url}}</a>
<!-- v-bind 也可以缩写为 :url="friend.url" 。 -->
</div>
</div>
`
});
这样我们就实现了一个可复用的 Vue 组件了,而且上面的问题我们已经完美解决了:
- 如果我们新增了一个朋友,就只需要在页面相应地方里面写一句:
<friend description="描述" url="网址">朋友的名字</friend>
Vice versa,如果我们需要修改卡片的样式,我们只需要修改组件的
template
里面的代码(当然你可以进一步将 CSS 分离出来)。本方法用的是 Vue 组件,它不会与原有的 Vue App 冲突(不过组件必须要写在 Vue App 里面。)
参考
如果你对上文所说内容仍有疑惑,可以翻看下面的链接。
后记
复制粘贴永远都是愚蠢的做法,而反人类的设计早有一日会被崭新的设计替代。
How can we do better?
这句话是 Robert Sedgewick 老先生在算法公开课里面经常提到的。只有不断思考How can we do better
,认知才会不断提高。否则对着一个愚蠢的做法沾沾自喜,永远不会有进步。
另外有问题的话,欢迎在评论区交流。
上次修改於 2020-03-16