该系列是为了让看过Vue官方文件或学过Vue但是却不知道怎麽下手去重构现在有的网站而去规画的系列文章,在这边整理了许多我自己使用Vue重构很多网站的经验分享给读者们。
在前面的章节,我们讲了许多 vue3 directive 的使用方式还有实际应用,接下来我们要把我们前面所讲的 Skeleton
还有我们的 directive
给结合在一起,做一个组合的实战应用。
You should use Skeleton : https://ithelp.ithome.com.tw/articles/10260925
这就是我们要处理,透过 directive + skeleton 完成以下的实际案例。
首先我先把资料给拿到手,我透过 axios
来拿资料
<script>
import { ref, onMounted } from "vue";
import axios from "axios";
export default {
setup() {
const postCard = ref([]);
const isLoad = ref(true);
onMounted(() => {
axios
.get("https://60bd9841ace4d50017aab3ec.mockapi.io/api/post_card")
.then((res) => {
postCard.value = res.data;
isLoad.value = false;
});
});
return {
postCard,
isLoad,
};
},
};
</script>
这边会看到我宣告了两笔资料,postCard
是我拿来存放 API 回来的资料,isLoad
是让我判断 API 的资料回来没有,接下来我们来看一下我们的 html 的部分
<template>
<div class="card" v-for="card in postCard" :key="card.id">
<header>
<img v-src="card.avatar" class="avatar load" />
<div>
<h1 :class="{ load: isLoad }">{{ isLoad ? "" : card.name }}</h1>
<p :class="{ load: isLoad }" v-timeformat="card.post_date"></p>
</div>
</header>
<p :class="['content', { load: isLoad }]">
{{ isLoad ? "" : card.content }}
</p>
<img class="post_photo load" v-src="card.photo" alt="" />
</div>
</template>
首先你会看到图片的地方我使用了 v-src
的这个模板语法,这就是我们在上一个章节所提到的用 directive
包起来的方法。
app.directive("src", (el, binding) => {
if (binding.value) {
const img = new Image();
img.src = binding.value;
img.onload = () => {
el.src = binding.value;
};
}
});
然後所有跟文字有关的地方都加上了一个 load
的class,这个 load
的class 就是为了让我们可以在资料回来以前,让我们的文字区块出现灰色色块所准备的,然後再里面的内文我用了 isLoad
来判断要不要让文字显示出来。
h1.load, p.load {
display: block;
width: 300px;
height: 14px;
background-color: #ededed;
color: rgba(#fff, 0);
}
@keyframes loading {
to {
background-position-x: -20%;
}
}
.load {
background: linear-gradient(
100deg,
rgba(256, 256, 256, 0) 30%,
rgba(256, 256, 256, 0.5) 50%,
rgba(256, 256, 256, 0) 30%
)
#ededed;
background-size: 200% 100%;
background-position-x: 180%;
animation: 2s loading ease-in-out infinite;
}
透过这样的方式我就可以很简单的处理图片的 load
以及 Skeleton
所需要显示的那些区块
import dayjs from "dayjs";
// 其他省略...
app.directive("timeformat", {
mounted(el, binding) {
const time = dayjs(binding.value).format("YYYY年MM月DD日");
el.innerText = time;
},
});
最後时间的部分处理就用了 v-timeformat
这个方法就大功告成了。
以下就是完整的程序码的部分
// index.js
import { createApp } from "vue";
import App from "./App.vue";
import dayjs from "dayjs";
const app = createApp(App);
app.directive("src", (el, binding) => {
if (binding.value) {
const img = new Image();
img.src = binding.value;
img.onload = () => {
el.src = binding.value;
};
}
});
app.directive("timeformat", {
mounted(el, binding) {
const time = dayjs(binding.value).format("YYYY年MM月DD日");
el.innerText = time;
},
});
app.mount("#app");
// App.vue
<script>
import { ref, onMounted } from "vue";
import axios from "axios";
export default {
setup() {
const postCard = ref([]);
const isLoad = ref(true);
onMounted(() => {
axios
.get("https://60bd9841ace4d50017aab3ec.mockapi.io/api/post_card")
.then((res) => {
postCard.value = res.data;
isLoad.value = false;
});
});
return {
postCard,
isLoad,
};
},
};
</script>
<template>
<div class="card" v-for="card in postCard" :key="card.id">
<header>
<img v-src="card.avatar" class="avatar load" />
<div>
<h1 :class="{ load: isLoad }">{{ isLoad ? "" : card.name }}</h1>
<p :class="{ load: isLoad }" v-timeformat="card.post_date"></p>
</div>
</header>
<p :class="['content', { load: isLoad }]">
{{ isLoad ? "" : card.content }}
</p>
<img class="post_photo load" v-src="card.photo" alt="" />
</div>
</template>
<style lang="scss">
.card {
width: 400px;
height: auto;
background-color: #fff;
box-shadow: 0 0 5px rgba(#000, 0.3);
margin: 0 auto 30px auto;
header {
display: flex;
padding: 10px 10px 0px 10px;
margin: 0 0 5px 0;
color: #666;
h1 {
font-size: 15px;
}
p {
font-size: 13px;
}
}
p.content {
font-size: 14px;
padding: 0px 10px 10px 10px;
color: #666;
&.load {
display: block;
width: 200px;
height: 14px;
background-color: #ededed;
color: rgba(#fff, 0);
margin: 10px 10px 10px 10px;
}
}
}
img.avatar {
width: 40px;
height: 40px;
border-radius: 50px;
margin-right: 10px;
background-color: #ededed;
}
img.post_photo {
width: 100%;
height: 300px;
background-color: #ededed;
}
h1.load {
display: block;
width: 300px;
height: 14px;
background-color: #ededed;
margin-bottom: 10px;
color: rgba(#fff, 0);
}
p.load {
display: block;
width: 100px;
height: 14px;
background-color: #ededed;
color: rgba(#fff, 0);
}
@keyframes loading {
to {
background-position-x: -20%;
}
}
.load {
background: linear-gradient(
100deg,
rgba(256, 256, 256, 0) 30%,
rgba(256, 256, 256, 0.5) 50%,
rgba(256, 256, 256, 0) 30%
)
#ededed;
background-size: 200% 100%;
background-position-x: 180%;
animation: 2s loading ease-in-out infinite;
}
</style>
我们今天特别把之前所讲过的东西给组合在一起 (Skeleton
跟 directive
),就是让大家知道其实我们在实际的开发上面,技术处理都是复合式的应用,不会只使用单一的概念来进行开发,所以特别把这两个组合应用分享给大家知道,也是希望大家在实际开发的时候可以更加的融会贯通,那今天就先到这边告一个段落了,我们明天见罗!
Ps. 购买的时候请登入或注册该平台的会员,然後再使用下面连结进入网站点击「立即购课」,这样才可以让我获得更多的课程分润,还可以帮助我完成更多丰富的内容给各位。
我有开设了一堂专门针对Vue3从零开始教学的课程,如果你觉得不错的话,可以购买我课程来学习
https://hiskio.com/bundles/9WwPNYRpz?s=tc
那如果对於JS基础不熟的朋友,我也有开设JS的入门课程,可以参考这个课程
https://hiskio.com/bundles/b9Rovqy7z?s=tc
Mike 的 Youtube 频道
Mike的medium
MIke 的官方 line 帐号,好友搜寻 @mike_cheng
<<: [Day04] TS:如何把物件型别的所有属性名称取出变成 union type?试试看 keyof 吧!
triplet loss 接下来的Loss function为triplet loss 是为2015...
大家好,在开始之前先祝大家中秋节快乐~~ 监控 (Monitor) 最常见的监控方法为仪表板 (Da...
在 CLOUDWAYS❐ 中,提供了5大云端主机供应商的方案☞ linode 、 VULTR 、 D...
WebRTC 在实作上遇到蛮多难题的,想要转成文章,理解程度仍然不足,只能花更多时间来研究了,不确定...
大家好,我是长风青云。今天是铁人赛第三天,也是中秋连假第一天。 youtube影片在上字幕的部分,後...