摘要
其實建立一個博客系統是非常簡單的,有很多開源的程序,如果你不喜歡博客系統,也可以自己開發,也可以自己簡單做一個。我這次就是用Vue.js和php做後端服務實現一個簡單的博客。
界面
代碼結構
代碼
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>VueBlog</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0,viewport-fit=cover">
<script src="./static/js/vue.min.js"></script>
<script src="./static/js/vue-router.min.js"></script>
<script src="./static/js/axios.min.js"></script>
<link rel="stylesheet" href="./static/css/app.css">
</head>
<body>
<div id="app">
<router-view></router-view>
</div>
<script src="./static/js/app.js"></script>
</body>
</html>
static/js/app.js
// 定義文章列表組件
const BlogList = {
template: `
<div class="container">
<div class="header">
<span class="logo">
<img src="./static/img/logo.jpg" />
</span>
<h2>TANKING,熱愛創作!</h2>
<span class="tag">
<a href="https://github.com/likeyun?tab=repositories" target="_blank">
<img src="./static/img/github.png" />
</a>
</span>
</div>
<div v-if="isLoading" class="loading-message">加載中...</div>
<ul v-infinite-scroll="loadMoreBlogs" infinite-scroll-disabled="loadingMore">
<li v-for="blog in blogs" :key="blog.blog_id">
<router-link :to="'/blog/' + blog.blog_id">
<p class="blog_title">{{ blog.blog_title }}</p>
<p class="blog_info">
<span>{{ blog.blog_category }}</span>
<span>{{ blog.blog_time }}</span>
<span>{{ blog.blog_pv }} 閲讀</span>
</p>
</router-link>
</li>
</ul>
<div class="error-message" v-if="getFail">{{ getFail }}</div>
</div>`,
// 數據
data() {
return {
blogs: [], // 列表數據
getFail: null, // 加載失敗
isLoading: true, // 加載中
currentPage: 0, // 當前頁碼
loadingMore: false // 是否正在加載更多內容
};
},
async created() {
// 加載初始文章列表
await this.loadMoreBlogs();
},
mounted() {
// 監聽滾動事件
window.addEventListener('scroll', this.handleScroll);
},
methods: {
// 監聽滾動事件
handleScroll() {
const scrollY = window.scrollY;
const windowHeight = window.innerHeight;
const documentHeight = document.documentElement.scrollHeight;
if (scrollY + windowHeight >= documentHeight - 200 && !this.loadingMore) {
// 當用户滾動到接近底部並且沒有正在加載更多數據時
this.loadMoreBlogs();
}
},
// 異步加載列表
async loadMoreBlogs() {
try {
// 正在加載更多數據
this.loadingMore = true;
const response = await axios.get('./server/getBlogList.php', {
params: {
p: this.currentPage + 1
}
});
if (response.data.code === 200) {
// 獲取成功
this.blogs.push(...response.data.blogList);
this.currentPage++;
} else if (response.data.code === 202) {
// 已到最後一頁
this.getFail = '已到最後一頁';
// 銷燬監聽事件
window.removeEventListener('scroll', this.handleScroll);
} else {
// 獲取失敗
this.getFail = '獲取博客列表失敗';
}
// 隱藏加載中
this.isLoading = false;
} catch (error) {
// 獲取失敗
this.getFail = '獲取博客列表失敗';
console.error(error);
} finally {
// 加載完成
this.loadingMore = false;
}
}
}
};
// 文章正文組件
const BlogDetail = {
template: `
<div class="container">
<div v-if="isLoading" class="loading-message">加載中...</div>
<div v-else>
<p class="blog_title blog_content_title">{{ blog.blog_title }}</p>
<p class="blog_info blog_content_info">
<span>{{ blog.blog_category }}</span>
<span>{{ blog.blog_author }}</span>
<span>{{ blog.blog_time }}</span>
<span>{{ blog.blog_pv }} 閲讀</span>
</p>
<div v-html="blog.blog_content" class="blog_content"></div>
<button class="like_button" @click="likeBlog" :disabled="isLiked">{{ blog.blog_like }} 贊</button>
</div>
<div class="error-message" v-if="getFail">{{ getFail }}</div>
</div>`,
// 數據
data() {
return {
blog: {},
getFail: null,
isLiked: false, // 是否已經點過贊
isLoading: true, // 加載中
};
},
// 異步加載內容
async created() {
try {
// 根據路由加載博客正文
var blogId = this.$route.params.id;
const response = await axios.get('./server/getBlogContent.php?blogId=' + blogId);
if (response.data.code == 200) {
// 獲取成功
this.blog = response.data.blogContent;
// 加載完成
this.isLoading = false;
}else{
// 獲取失敗
this.getFail = '獲取博客內容失敗';
}
} catch (error) {
// 獲取失敗
this.getFail = '獲取博客內容失敗';
console.error(error);
}
// 檢查本地存儲是否已點贊,如果已點贊則更新 isLiked
const isLiked = localStorage.getItem('liked_' + blogId);
if (isLiked === 'true') {
// 如果有緩存就設置為你已經點過贊
this.isLiked = true;
}
},
// 方法
methods: {
// 記錄點贊
likeBlog() {
if (!this.isLiked) {
axios.post('./server/likeBlog.php?blogId=' + this.blog.blog_id)
.then(response => {
if (response.data.code === 200) {
// 更新點贊數量
this.blog.blog_like++;
// 將點贊狀態設置為已點贊
this.isLiked = true;
// 點贊成功後,將點贊狀態保存到本地存儲
localStorage.setItem('liked_' + this.blog.blog_id, 'true');
}
})
.catch(error => {
console.error(error);
});
}
}
}
};
// 定義路由
const routes = [
{ path: '/', component: BlogList },
{ path: '/blog/:id', component: BlogDetail }
];
const router = new VueRouter({
routes
});
// 創建Vue實例並掛載到app節點
new Vue({
el: '#app',
router
});
完整代碼
如需獲取後端服務、前端、樣式等完整代碼請下載:
https://afdian.net/item/279611c435d811eea89a52540025c377
演示
http://demo.likeyunba.com/blog/#/
作者
TANKING