直接在html中引入Vue.js的cdn来实现一个简单的博客

news2024/12/23 5:03:17

摘要

其实建立一个博客系统是非常简单的,有很多开源的程序,如果你不喜欢博客系统,也可以自己开发,也可以自己简单做一个。我这次就是用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
});

演示

http://demo.likeyunba.com/blog/#/

作者

TANKING

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/861110.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

逆向破解学习-单机斗地主

试玩 破解思路 9000 是成功的代码 Hook代码 import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class HookComJuneGameDouDiZhu extends HookImpl{ Override p…

实验室如何选择适合的LIMS实验室管理系统

实验室信息管理系统(LIMS)是从20世纪70年代末开始发展起来的&#xff0c;距今在国外已发展40多年。国内发展历史约20多年&#xff0c;且前十几年国内市场上主要是国外进口的LIMS产品&#xff0c;存在价格高、产品重&#xff0c;实施周期长等水土不服的情况。近十年开始&#xf…

matplotlib fig.legend()常用参数 包括位置调整和字体设置等

一、四种方法 legend() legend(handles, labels) legend(handleshandles) legend(labels)1 legend() labels自动通过绘图获取&#xff08;Automatic detection of elements to be shown in the legend&#xff09; # 第一种方法 ax.plot([1, 2, 3], labelInline label) ax.l…

竞赛项目 深度学习实现语义分割算法系统 - 机器视觉

文章目录 1 前言2 概念介绍2.1 什么是图像语义分割 3 条件随机场的深度学习模型3\. 1 多尺度特征融合 4 语义分割开发过程4.1 建立4.2 下载CamVid数据集4.3 加载CamVid图像4.4 加载CamVid像素标签图像 5 PyTorch 实现语义分割5.1 数据集准备5.2 训练基准模型5.3 损失函数5.4 归…

仿到位|独立版家政上门预约服务小程序家政保洁师傅上门服务小程序上门服务在线派单源码

上门预约服务派单小程序家政 小程序 同城预约 开源代码 独立版. 程序完整,经过安装检测,可放心下载安装。 适合本地的一款上门预约服务小程序,功能丰富,适用多种场景。 程序功能:城市管理/小程序DIY/服务订单/师傅管理/会员卡功能/营销功能/文章功能等等

业绩难言乐观,皓泽电子撤回上市申请,小米等为其关联方

撰稿|行星 来源|贝多财经 8月8日&#xff0c;深圳证券交易所披露的信息显示&#xff0c;由于河南皓泽电子股份有限公司&#xff08;下称“皓泽电子”&#xff09;及其保荐人主动要求撤回申请文件&#xff0c;深交所终止了皓泽电子的发行注册程序。 据此前招股书披露&#xff…

大模型的数据隐私问题有解了,浙江大学提出联邦大语言模型

作者 | 小戏、Python 理想化的 Learning 的理论方法作用于现实世界总会面临着诸多挑战&#xff0c;从模型部署到模型压缩&#xff0c;从数据的可获取性到数据的隐私问题。而面对着公共领域数据的稀缺性以及私有领域的数据隐私问题&#xff0c;联邦学习&#xff08;Federated Le…

火车头采集伪原创插件【php源码】

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python代码大全和用法&#xff0c;python代码大全简单&#xff0c;现在让我们一起来看看吧&#xff01; 火车头采集ai伪原创插件截图&#xff1a; 1、题目&#xff1a;列表转换为字典。 程序源代码&#xff1a; 1 #!/us…

外部节点访问 k8s 集群内的 starrocks

问题描述 用kubeadm在虚拟机搭建了k8s&#xff0c;按starrocks官网步骤&#xff0c;用k8s部署了starrocks 部署成功&#xff1a; 在 k8s集群内节点访问到 sr&#xff1a;&#xff08;通过 clusterIP &#xff09; mysql -h 10.97.182.109 -uroot -P 9030 k8s 节点内访问成功…

windows10开启远程连接

目录 开启远程连接远程连接 开启远程连接 右击电脑图标->属性 点击 远程设置 远程连接 找到 远程桌面连接 点击 远程桌面连接 输入远程ip 10.0.8.5 然后点击连接 4.输入默认用户名new的密码&#xff0c;然后确定&#xff0c;搞定。

tensorflow-gpu cuda cudNN tensorRT 安装

tensorflow-gpu cuda cudNN tensorRT 安装 tensorflow-gpu 版本对应关系 https://tensorflow.google.cn/install/source#gpu CUDA 安装 安装文档 https://docs.nvidia.com/cuda/ linux 安装文档 &#xff1a;https://docs.nvidia.com/cuda/cuda-installation-guide-linux/i…

爬虫如何应对网站的反爬机制?如何查找user-agent对应的值

import requestsurl https://movie.douban.com/top250 response requests.get(url) # 查看结果 print(response)在requests使用一文中我们有讲到&#xff0c;当状态码不是200时表示爬虫不可用&#xff0c;也就是说我们获取不到网页源代码。但是我们还是可以挣扎一下&#xff…

WordPress博客发布到公网可访问【 windows系统及linux系统操作】

文章目录 1. 免费注册并下载安装cpolar内网穿透1.1 windows系统1.2 linux系统 2. 将内网映射到公网3. 获取所映射的公网地址 要将自己搭建的个人WordPress博客网站发布到公网可访问&#xff0c;比较常规的做法是买服务器、域名&#xff0c;将其部署到服务器上&#xff0c;备案发…

定制 ChatGPT 以满足您的需求 自定义说明

推荐&#xff1a;使用 NSDT场景编辑器 快速助你搭建可二次编辑的3D应用场景 20 月 <> 日&#xff0c;OpenAI 宣布他们正在引入带有自定义说明的新流程&#xff0c;以根据您的特定需求定制 ChatGPT。 什么是自定义说明&#xff1f; 新的测试版自定义指令功能旨在通过防止…

.NET6使用SqlSugar操作数据库

1.//首先引入SqlSugarCore包 2.//新建SqlsugarSetup类 public static class SqlsugarSetup{public static void AddSqlsugarSetup(this IServiceCollection services, IConfiguration configuration,string dbName "ConnectString"){SqlSugarScope sqlSugar new Sq…

后端开发7.轮播图模块【mongdb开发】

概述 轮播图模块数据库采用mongdb开发 效果图 数据库设计 创建数据库 use sc; 添加数据 db.banner.insertMany([ {bannerId:"1",bannerName:"商城轮播图1",bannerUrl:"http://xx:8020/img/轮播图/shop1.png"}, {bannerId:"2"…

人大金仓助力某大型金融机构业务系统异地容灾优化升级

日前&#xff0c;人大金仓助力某大型金融机构应收账款融资服务平台异地容灾项目顺利上线&#xff0c;保证了平台系统运行的连续性和数据安全&#xff0c;为充分发挥平台的融资功能&#xff0c;缓解中小微企业融资难提供了强有力的保障。 “ 缓解中小微企业融资难 某大型金融机构…

Java算法_ 杨辉三角(LeetCode_Hot100)

题目描述&#xff1a;题目描述&#xff1a;给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 获得更多&#xff1f;算法思路:代码文档&#xff0c;算法解析的私得。 运行效果 完整代码…

关于Object 0 = new Object() 的追魂九连问

文章目录 对象的创建过程对象的组成解析普通对象**结果分析&#xff1a;**给对象添加属性注意事项 补充jvm压缩指针栗子&#xff1a; 对象头包含什么对象怎么定位&#xff1f;**句柄方式和直接引用的优缺点&#xff1a;** 对象怎么分配&#xff1f;为什么hotspot不使用c对象来代…

【JavaScript】一文详解事件循环机制

目录 一、是什么 二、同步任务和异步任务 三、宏任务和微任务 小结&#xff1a;微任务是跟屁虫&#xff0c;一直跟着当前宏任务后面代码执行到一个微任务就跟上&#xff0c;一个接着一个。 例子理解&#xff1a; 五、题目巩固 六、总结 一、是什么 首先JavaScript是一种…