【腾讯云 Cloud Studio 实战训练营】沉浸式体验编写一个博客系统

@toc

项目运行

点击下面按钮即可获得该应用哦! 快来试试吧

点击运行项目

前言

欢迎参加腾讯云 Cloud Studio 实战训练营!在本次训练营中,我们将通过沉浸式体验,带您一步步编写一个基于 Nuxt.js 的静态博客系统。无论您是初学者还是有一定编程经验的开发者,本训练营都将为您提供一个深入了解和掌握 Nuxt.js 技术以及静态网站开发的机会。

使用 Nuxt.js 作为前端框架,我们将能够充分利用其强大的功能和优势,快速搭建一个高效、可扩展的静态博客系统。Nuxt.js 是基于 Vue.js 的服务端渲染框架,结合了单页应用程序(SPA)和静态生成模式(SSG),使得我们可以轻松构建出具有良好用户体验的博客系统。

在这个过程中,您将学习到

  1. 如何使用Cloud Studio 进行项目开发
  2. Cloud Studio 项目如何链接到coding 作为项目的管理仓库
  3. 如和使用python 来爬取你的csdn 博客信息
  4. Nuxt.js 的安装和基本配置:了解如何创建一个新的 Nuxt.js 项目,以及对其基本配置进行调整。
  5. 页面和路由设计:学习如何使用 Nuxt.js 创建不同的页面,以及如何配置路由,实现页面之间的导航。
  6. layout 模块如何使用,清晰规划layout
  7. 登录模块的动画效果等

项目中技术栈

  • Vue.js:JavaScript 框架
  • Nuxt.js:Vue.js 的通用应用框架
  • Element UI:基于 Vue.js 的 UI 组件库

新建工作空间

参考以下步骤来创建一个属于你自己的工作空间

登录(注册)Cloud Studio 账号:

打开Cloud Studio网址(https://cloudstudio.net/),有三种注册登录方式 , 选择一种即可

进入 Cloud Studio 控制台:

点击左下角的 新建工作空间

配置工作空间参数:

在弹出的创建工作空间窗口中,您需要进行以下配置:

  • 空间名称
  • 空间描述
  • 工作类别
  • 代码来源
  • 选择仓库服务商
  • 开发环境
  • 规格配置 注意 这里我选择的是coding 作为仓库服务商, 因此需要自己注册一个coding 账户, 这里不做详细讲解 如图 输入coding的域名前缀就可以了

完整配置

确认并创建工作空间:

完成上述配置后,点击 "创建" 按钮确认创建新的工作空间, 你会惊喜的发现 这个与vscode 惊人的相似

项目搭建

接下来就开始进行项目搭建环节

注意事项 在搭建Nuxt项目时,你需要注意以下几个方面:

  1. 安装Node.js和npm: Nuxt是基于Node.js开发的,因此首先要确保在本地安装了Node.js和npm。可以从官方网站上下载并安装最新版本的Node.js,它会附带安装npm。比如本项目 用的是 node 19.0.0 这版本, 建议 采用nvm 进行版本管理
  2. 创建新项目: 使用Nuxt提供的命令行工具创建新的Nuxt项目。打开终端窗口,切换到项目的目录中,然后执行npx create-nuxt-app <project-name>命令。根据提示选择要使用的模板和配置项。
  3. 配置项目: 在创建项目后,你可以根据自己的需求进行一些配置。这包括选择UI框架、路由配置、样式预处理器等。可以修改nuxt.config.js文件来进行配置。本项目中所需要配置的地方
代码语言:txt
复制
需要再`nuxt.config.js`中配置`server` 如下
代码语言:txt
复制
```js
代码语言:txt
复制

server: {

代码语言:txt
复制

port: 3000, // default: 3000

代码语言:txt
复制

host: '0.0.0.0' // default: localhost

代码语言:txt
复制
  }
代码语言:txt
复制

meta:中加上代码 { name: 'referrer', content: 'no-referrer' }, 来进行图片的加载

拓展内容

  1. 开发和构建: 使用Nuxt进行开发时,可以在pages目录下创建页面组件,Nuxt会自动根据文件名生成路由。可以在layouts目录下创建布局组件,用于定义页面的整体布局。使用Nuxt提供的命令npm run dev启动本地开发服务器,进行实时预览。使用npm run build命令构建项目,生成静态文件。
  2. SEO优化: Nuxt默认使用服务端渲染(SSR),可以优化SEO(搜索引擎优化)。在每个页面组件中,可以使用head方法来设置页面的标题、meta标签等信息,这些信息将在服务端被渲染。
  3. 部署项目: 在部署Nuxt项目时,你可以选择将项目部署到服务器上或者使用静态文件托管服务。如果选择部署到服务器上,需要确保服务器上已经安装了Node.js和npm,并按照说明运行npm installnpm run build命令。 配置nuxt 脚手架

使用命令 npx create-nuxt-app <项目名> 创建一个nuxt 的脚手架

掉出终端 , 输出 指令 回车运行, 等待项目下载

成功搭建后效果图, 以及脚手架配置

运行项目

运行项目的指令

代码语言:txt
复制
 cd blog
 npm run dev

报错信息

运行时我发现了一个错误,如下所示

代码语言:shell
复制
blog git:(master) ✗ npm run dev

> blog@1.0.0 dev
> nuxt

internal/modules/cjs/loader.js:892
throw err;
^

Error: Cannot find module 'node:util'
Require stack:

  • /workspace/myblog/blog/node_modules/consola/dist/shared/consola.deac7d5a.cjs

  • /workspace/myblog/blog/node_modules/consola/dist/shared/consola.4bbae468.cjs

  • /workspace/myblog/blog/node_modules/consola/dist/index.cjs

  • /workspace/myblog/blog/node_modules/consola/lib/index.cjs

  • /workspace/myblog/blog/node_modules/@nuxt/utils/dist/utils.js

  • /workspace/myblog/blog/node_modules/@nuxt/cli/dist/cli-index.js

  • /workspace/myblog/blog/node_modules/@nuxt/cli/dist/cli.js

  • /workspace/myblog/blog/node_modules/nuxt/bin/nuxt.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:889:15)
    at Function.Module._load (internal/modules/cjs/loader.js:745:27)
    at Module.require (internal/modules/cjs/loader.js:961:19)
    at require (internal/modules/cjs/helpers.js:92:18)
    at Object.<anonymous> (/workspace/myblog/blog/node_modules/consola/dist/shared/consola.deac7d5a.cjs:3:19)
    at Module._compile (internal/modules/cjs/loader.js:1072:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)
    at Module.load (internal/modules/cjs/loader.js:937:32)
    at Function.Module._load (internal/modules/cjs/loader.js:778:12)
    at Module.require (internal/modules/cjs/loader.js:961:19) {
    code: 'MODULE_NOT_FOUND',
    requireStack: [
    '/workspace/myblog/blog/node_modules/consola/dist/shared/consola.deac7d5a.cjs',
    '/workspace/myblog/blog/node_modules/consola/dist/shared/consola.4bbae468.cjs',
    '/workspace/myblog/blog/node_modules/consola/dist/index.cjs',
    '/workspace/myblog/blog/node_modules/consola/lib/index.cjs',
    '/workspace/myblog/blog/node_modules/@nuxt/utils/dist/utils.js',
    '/workspace/myblog/blog/node_modules/@nuxt/cli/dist/cli-index.js',
    '/workspace/myblog/blog/node_modules/@nuxt/cli/dist/cli.js',
    '/workspace/myblog/blog/node_modules/nuxt/bin/nuxt.js'
    ]
    }
    ➜ blog git:(master) ✗

解决错误

根据错误信息显示,是找不到模块 'node:util',导致引发了错误。

可以尝试以下办法解决

根据错误信息显示,依然是找不到模块 'node:util',导致引发了错误。这可能是由于依赖关系问题或缺失的模块引起的。

您可以尝试以下步骤来解决这个问题:

  1. 清除 npm 缓存:在终端中执行以下命令清除 npm 缓存:
代码语言:shell
复制
npm cache clean --force
  1. 删除 package-lock.json 文件和 node_modules 目录:在项目根目录下执行以下命令删除 package-lock.json 文件和 node_modules 目录:
代码语言:shell
复制
rm package-lock.json
rm -rf node_modules
  1. 更新node 版本到19.0.0操作步骤如下:

- nvm ls

  • nvm install 19.0.0
  • nvm use 19.0.0

    1. 重新安装依赖
      • npm install
    2. 运行项目
      • npm run dev

    脚手架运行预览

    问题

    这里直接访问 http://172.16.21.246:3000/ 是不行的 有点击弹窗的信息进行访问, 如图

    开启博客代码

    配置layout

    代码语言:html
    复制
    <template>
    

<div>
<el-card class="nav">
<h1>若城的博客</h1>

<div class="left">
<el-row :gutter="20">
<el-col :span="8" v-for="item in nav" :key="item.label">

    &lt;span class=&#34;mynav&#34; @click=&#34;handleJump(item.route)&#34;&gt;{{item.label}}&lt;/span&gt;
  &lt;/el-col&gt;

&lt;/el-row&gt;

</div>

<div class="right">
<el-row :gutter="20">
<el-col :span="12"><span @click="handleGoLogin(1)" class="mynav">登录</span></el-col>
<el-col :span="12" ><span @click="handleGoLogin(2)" class="mynav">注册</span></el-col>
</el-row>
</div>
</el-card>
<nuxt />

</div>
</template>
<script>
export default {
data() {
return {
nav:[
{
label:'首页',
route:'index'
},
{
label:'博客画廊',
route:'photo'
},
{
label:'我的画廊',
route:'about'
},
]
}
},
methods: {
handleJump(url){
this.$router.push({name:url})
},
handleGoLogin(idx){
this.$router.push({name:'login'})

}
},
}
</script>
<style lang="scss" scoped>
.nav{

}
h1{
height: 30px;
cursor: pointer;

line-height: 30px;
}
::v-deep .el-card__body{
display: flex;
justify-content: space-between;
}
.left{
width: 30%;
cursor: pointer;
}
.right{
width: 10%;
cursor: pointer;

}
</style>

总结说明

模板部分:

  • 使用了<el-card>组件包裹整个导航栏。
  • <h1>标签显示了博客的标题,具有点击事件绑定,当被点击时会触发handleJump()方法。
  • <div class="left"><div class="right">分别表示导航栏左侧和右侧的区域,使用了Element UI的<el-row><el-col>组件来实现栅格布局。
  • 在左侧区域中,使用了v-for指令遍历nav数组中的对象,生成对应的导航项,并绑定了点击事件。
  • 在右侧区域中,同样使用了<el-col>组件生成两个导航项,分别是"登录"和"注册",并绑定了点击事件。
  • 在最后,使用了<nuxt />组件来展示其他页面内容。

脚本部分:

  • data中定义了一个nav数组,其中包含了导航栏的各个项,每个项包括一个label标签和一个route路由名称。
  • methods中定义了两个方法:handleJump(url)用于通过router.push()</code>方法实现页面跳转,<code>handleGoLogin(idx)</code>也是通过<code>router.push()方法实现跳转到登录页面。

样式部分:

  • .nav类定义导航栏整体的样式。
  • h1标签设置了标题的样式,包括高度、光标类型以及行高等。
  • ::v-deep .el-card__body选择器通过::v-deep关键词,使得内部样式可以影响该组件下的子组件,这里用来设置导航栏内部元素的样式。
  • .left.right类分别设置了左侧和右侧区域的宽度和光标类型。

layout 部分的代码主要实现的是一个简单的导航栏组件,并使用Nuxt来展示其他页面内容。点击导航项会触发相应的跳转事件。

首页配置

代码语言:html
复制
<template>
<div class="container">
<el-container>
<el-aside width="500px">
<el-card class="box-card">
<div slot="header">
<span>关于我</span>
</div>
<div class="wrapper">
<div class="image">
<el-avatar shape="square" :size="200" :src="pho"></el-avatar>
</div>
<div class="text">
{{aboutMe}}
</div>
</div>
</el-card>

  &lt;el-card class=&#34;box-card&#34;&gt;
    &lt;clock /&gt;
  &lt;/el-card&gt;
&lt;/el-aside&gt;
&lt;el-main&gt;
  &lt;el-card v-for=&#34;(item, index) in blogJson&#34; :key=&#34;index&#34;&gt;
    &lt;el-row :gutter=&#34;20&#34;&gt;
      &lt;el-col :span=&#34;20&#34; class=&#34;mycol&#34;&gt;
        &lt;h3 @click=&#34;handleLink(item.blogLink)&#34;&gt;{{ item.title }}&lt;/h3&gt;
        &lt;p&gt;{{ item.desc }}&lt;/p&gt;
      &lt;/el-col&gt;

      &lt;el-col :span=&#34;4&#34;&gt;
        &lt;el-image
          style=&#34;width: 100px; height: 100px&#34;
          :src=&#34;item.imgLink&#34;
          fit=&#34;fill&#34;
        &gt;&lt;/el-image&gt;
      &lt;/el-col&gt;
    &lt;/el-row&gt;
  &lt;/el-card&gt;
&lt;/el-main&gt;

</el-container>
</div>
</template>

<script>
import pho from "../assets/img/1.jpg";
import blogJson from "../assets/result.json";
import clock from "../components/Clock.vue"

export default {
layout: "Myblog",
data() {
return {
pho,
blogJson,
aboutMe: 大家好,我是一名专注于 Python 和前端技术的技术讲解者。 我擅长将复杂的技术概念转化为简单易懂的语言,帮助初学者快速入门, 并满足高级开发者对更深入理解的需求。 作为一位资深的 Python 开发者,我具备广泛的编程经验和深厚的技术功底。我熟练掌握 Python 语言的各种特性和库,能够灵活运用它们解决实际问题。 不论是爬虫、数据分析、后端开发还是机器学习,我都能够提供高效、可靠的解决方案。 如果你对 Python 或前端技术有任何疑问或需要帮助,欢迎与我联系。无论是入门指导、项目建议还是技术咨询, 我都会竭诚为您提供帮助。让我们一起探索技术的魅力,共同成长和进步!,
};
},
component(){
clock
},
methods: {
handleLink(item){
// window.location.href =
window.open(item, "_blank")
}
},
};
</script>
<style lang="scss" scoped>
// .box-card{
// padding: 30px 0px 30px 0;
// }
.wrapper {
overflow: hidden; /* 确保容器可以包含浮动元素 /
width: 500px; /
文字区域宽度 */
}

.text {
}

.image {
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
border: 2px solid #f0f0f0;
float: left;
shape-outside: circle();
}
.mycol{
cursor: pointer;
}

::v-deep .el-card {
margin-bottom: 20px;
}
</style>

总结说明

模板部分:

  • 使用了<el-container>组件来创建一个容器,包含了左侧的侧边栏(<el-aside>)和右侧的主要内容区域(<el-main>)。
  • 侧边栏中包含了两个<el-card>组件,分别用于展示关于我和时钟。
  • 关于我的部分使用了一个wrapper包裹,包含了一个头像(<el-avatar>)和一个文本区域,文本区域中显示了关于我的内容。
  • 主要内容区域中使用了v-for指令遍历blogJson数组中的对象,在每个对象对应的<el-card>中展示博客的标题、描述和图片。

脚本部分:

  • 使用了import语句引入了一些资源文件和组件。
  • data函数返回了一个包含了一些数据的对象,包括头像、博客数据和关于我的内容。
  • component属性中注册了一个名为clock的组件。
  • methods中定义了一个handleLink(item)方法,当博客列表中的标题被点击时,会在新窗口中打开对应的博客链接。

样式部分:

  • 使用了SCSS预处理器语法。
  • wrapper类用于设置关于我部分文字区域的样式。
  • image类用于设置头像区域的样式,包括宽度、高度、边框等。
  • .mycol类设置了博客列表标题的样式,包括光标类型为指针。
  • ::v-deep .el-card选择器通过::v-deep关键词,使得内部样式可以影响该组件下的子组件,这里用来设置博客列表项之间的间距。

首页部分的代码主要实现的是关于我和博客列表的页面,使用Element UI的组件和样式进行展示。关于我部分展示了一张头像和一段文字信息,博客列表展示了多个博客项,每个博客项包括标题、描述和图片。点击博客标题会在新窗口中打开对应的博客链接。

其他页面

由于每个页面都有不同的用处, 这里就不做过多讲解说明, 对于这个博客感兴趣的朋友可以在文章最下面找到项目地址哦!

效果预览

项目目录结构

代码语言:txt
复制
blog
|-- myblog
|-- .editorconfig // 代码编辑器的配置文件
|-- .gitignore // Git 版本控制忽略文件列表
|-- README.md // 项目的说明文档
|-- nuxt.config.js // Nuxt.js 的配置文件
|-- package-lock.json // npm 生成的锁定依赖版本的文件
|-- package.json // 包含项目的元数据和依赖的配置文件
|-- tree.md // 当前目录结构的文档
|-- .nuxt // Nuxt.js 自动生成的文件夹
| |-- App.js // Nuxt.js 应用程序的入口文件
| |-- client.js // Nuxt.js 客户端的入口文件
| |-- empty.js // 空文件
| |-- index.js // Nuxt.js 核心库的入口文件
| |-- jsonp.js // JSONP 相关的功能代码
| |-- loading.html // 页面加载中的 HTML 文件
| |-- middleware.js // 中间件的代码
| |-- router.js // 路由的配置文件
| |-- router.scrollBehavior.js // 路由的滚动行为配置文件
| |-- routes.json // 路由的配置文件(JSON 格式)
| |-- server.js // Nuxt.js 服务器的入口文件
| |-- utils.js // Nuxt.js 的工具函数
| |-- components // Nuxt.js 自动生成的组件目录
| |-- layouts // 页面布局文件目录
| |-- mixins // Mixin 文件目录
| |-- vetur // Vetur 插件的配置文件目录
| |-- views // 视图文件目录
|-- assets // 静态资源文件目录
| |-- common.css // 共享的 CSS 样式文件
| |-- login.css // 登录页面的 CSS 样式文件
| |-- pat.svg // PAT 图标文件(可能是用户名的缩写)
| |-- result.json // 结果数据的 JSON 文件
| |-- img // 图片目录
| |-- 1.jpg // 图片文件
|-- components // 自定义组件目录
| |-- Clock.vue // 时钟组件
| |-- NuxtLogo.vue // Nuxt.js Logo 组件
| |-- Tutorial.vue // 教程组件
|-- layouts // 页面布局文件目录
| |-- Myblog.vue // "Myblog" 页面的布局文件
|-- pages // 页面文件目录
| |-- index.vue // 主页
| |-- about // 关于页面
| | |-- index.vue // 关于页面的主文件
| |-- login // 登录页面
| | |-- index.vue // 登录页面的主文件
| |-- photo // 照片页面
| |-- index.vue // 照片页面的主文件
|-- plugins // 插件文件目录
| |-- element-ui.js // Element UI 插件的配置文件
|-- static // 静态文件目录
| |-- favicon.ico // 网站的图标文件
| |-- heng // 文件夹
| |-- imgdata // 图像数据文件夹
|-- store // Vuex 的状态管理目录
|-- README.md // 状态管理的说明文档

上传代码到coding

设置coding 邮箱和账号

git config --global user.email "you@example.com"
git config --global user.name "Your Name"

git 提交

1.在我们的命令编辑器里初始化项目 git init
2.git add .

3.git commit -m '备注'

4.git remote add origin git@gitee.com:shiqingqing/test.git

5.git pull origin master

6.开始上传 输入git push -u origin master 这里可能会报错 所以建议不用这句 直接使用git push -u origin master -f 强制上传

总结说明

到目前位置 基本上已经将项目搭建完成了, 不过在使用Cloud Studio 的过程中确实存在一些问题,总结如下:

链接图片不显示

如图我的imgLink 是有效的https 地址 , 但是 实际上运行之后并没有显示出来, 随后我又换了几种方式,发现都不显示, 很难受

终端启动项目

我这个是nuxt项目, 终端启动的时候 会有默认的请求地址, 但是 这个地址并不生效, 相反需要打开终端弹窗的按钮才可以访问, 访问的地址与我自己监听的地址也不一样, 完全不符合习惯, 如图

关闭端口弹窗问题

启动项目之后关闭终端弹窗之后 , 就找不到这个弹窗了, 不知在哪里找到, 除非重启项目

文件同步运行问题

编辑文件的时候自动保存, 导致终端会热更新, 显得很乱, 而且出现的报错也很严重, 比如我一个闭合还没敲,但是终端已经运行了, 这时就会报错, 很难受啊

安装脚手架

在安装脚手架的时候,非常费时间,等了好久,希望可以改进下

优点

在安装项目的时候 , 我发现使用的node 版本不对但是, 我不清楚Cloud Studio 是否有nvm 版本管理工具, 尝试的敲了一下 nvm ls 发现, 竟然贴心的安装了nvm 版本控制, 这个很细节很好.

当然Cloud Studio 还有很多其他优点, 期待大家一起去体验感受一下哦!

资源

项目coding 地址

blog项目地址

Cloud Studio 地址

Cloud Studio

使用py脚本获取博客资源

代码语言:python
代码运行次数:0
复制
Cloud Studio 代码运行
import json
from selenium import webdriver

使用 Chrome 驱动程序创建一个 WebDriver 实例

driver = webdriver.Chrome()

访问指定的博客列表页面

url = 'https://blog.csdn.net/qq_33681891?type=blog'
driver.get(url)

定位博客列表中的每篇文章

articles = driver.find_elements('css selector', '.blog-list-box')

创建一个空列表用于存储结果

results = []

遍历每篇文章,获取图片、标题、简介和博客链接

for article in articles:
# 获取图片链接
img_elem = article.find_element('css selector', '.course-img')
img_src = img_elem.get_attribute('src')

# 获取标题
title_elem = article.find_element(&#39;css selector&#39;, &#39;h4&#39;)
title = title_elem.text

# 获取简介
desc_elem = article.find_element(&#39;css selector&#39;, &#39;.blog-list-content&#39;)
desc = desc_elem.text

# 获取博客链接
link_elem = article.find_element(&#39;css selector&#39;, &#39;a&#39;)
link = link_elem.get_attribute(&#39;href&#39;)

# 将结果添加到列表中
result = {
    &#39;图片链接&#39;: img_src,
    &#39;标题&#39;: title,
    &#39;简介&#39;: desc,
    &#39;博客链接&#39;: link
}
results.append(result)

关闭浏览器

driver.quit()

将结果以 JSON 格式写入文件

with open('result.json', 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=False, indent=4)

print('结果已保存到 result.json 文件中')