前言
欢迎参加腾讯云 Cloud Studio 实战训练营!在本次训练营中,我们将通过沉浸式体验,带您一步步编写一个基于 Nuxt.js 的静态博客系统。无论您是初学者还是有一定编程经验的开发者,本训练营都将为您提供一个深入了解和掌握 Nuxt.js 技术以及静态网站开发的机会。使用 Nuxt.js 作为前端框架,我们将能够充分利用其强大的功能和优势,快速搭建一个高效、可扩展的静态博客系统。Nuxt.js 是基于 Vue.js 的服务端渲染框架,结合了单页应用程序(SPA)和静态生成模式(SSG),使得我们可以轻松构建出具有良好用户体验的博客系统。
在这个过程中,您将学习到
如何使用 Cloud Studio 进行项目开发
Cloud Studio 项目如何链接到 coding 作为项目的管理仓库
如和使用 python 来爬取你的 csdn 博客信息
Nuxt.js 的安装和基本配置:了解如何创建一个新的 Nuxt.js 项目,以及对其基本配置进行调整。
页面和路由设计:学习如何使用 Nuxt.js 创建不同的页面,以及如何配置路由,实现页面之间的导航。
layout 模块如何使用,清晰规划 layout
登录模块的动画效果等
项目中技术栈
新建工作空间
参考以下步骤来创建一个属于你自己的工作空间
登录(注册)Cloud Studio 账号:
打开 Cloud Studio 网址(https://cloudstudio.net/),有三种注册登录方式 , 选择一种即可
进入 Cloud Studio 控制台:
点击左下角的 新建工作空间
配置工作空间参数:
在弹出的创建工作空间窗口中,您需要进行以下配置:
完整配置
确认并创建工作空间:
完成上述配置后,点击 "创建" 按钮确认创建新的工作空间, 你会惊喜的发现 这个与 vscode 惊人的相似
项目搭建
接下来就开始进行项目搭建环节
注意事项在搭建 Nuxt 项目时,你需要注意以下几个方面:
安装 Node.js 和 npm: Nuxt 是基于 Node.js 开发的,因此首先要确保在本地安装了 Node.js 和 npm。可以从官方网站上下载并安装最新版本的 Node.js,它会附带安装 npm。
比如本项目 用的是 node 19.0.0 这版本, 建议 采用 nvm 进行版本管理
创建新项目: 使用 Nuxt 提供的命令行工具创建新的 Nuxt 项目。打开终端窗口,切换到项目的目录中,然后执行npx create-nuxt-app <project-name>
命令。根据提示选择要使用的模板和配置项。
配置项目: 在创建项目后,你可以根据自己的需求进行一些配置。这包括选择 UI 框架、路由配置、样式预处理器等。可以修改nuxt.config.js
文件来进行配置。
本项目中所需要配置的地方
需要再nuxt.config.js
中配置server
如下
server: {
port: 3000, // default: 3000
host: '0.0.0.0' // default: localhost
}
复制代码
在 meta:
中加上代码 { name: 'referrer', content: 'no-referrer' },
来进行图片的加载
拓展内容
开发和构建: 使用 Nuxt 进行开发时,可以在pages
目录下创建页面组件,Nuxt 会自动根据文件名生成路由。可以在layouts
目录下创建布局组件,用于定义页面的整体布局。使用 Nuxt 提供的命令npm run dev
启动本地开发服务器,进行实时预览。使用npm run build
命令构建项目,生成静态文件。
SEO 优化: Nuxt 默认使用服务端渲染(SSR),可以优化 SEO(搜索引擎优化)。在每个页面组件中,可以使用head
方法来设置页面的标题、meta 标签等信息,这些信息将在服务端被渲染。
部署项目: 在部署 Nuxt 项目时,你可以选择将项目部署到服务器上或者使用静态文件托管服务。如果选择部署到服务器上,需要确保服务器上已经安装了 Node.js 和 npm,并按照说明运行npm install
和npm run build
命令。
配置 nuxt 脚手架
使用命令 npx create-nuxt-app <项目名>
创建一个 nuxt 的脚手架
掉出终端 , 输出 指令 回车运行, 等待项目下载
成功搭建后效果图, 以及脚手架配置
运行项目
运行项目的指令
报错信息
运行时我发现了一个错误,如下所示
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',导致引发了错误。这可能是由于依赖关系问题或缺失的模块引起的。
您可以尝试以下步骤来解决这个问题:
清除 npm 缓存:在终端中执行以下命令清除 npm 缓存:
删除 package-lock.json
文件和 node_modules
目录:在项目根目录下执行以下命令删除 package-lock.json
文件和 node_modules
目录:
rm package-lock.json
rm -rf node_modules
复制代码
更新 node 版本到 19.0.0
操作步骤如下:
nvm ls
nvm install 19.0.0
nvm use 19.0.0
重新安装依赖
npm install
运行项目
npm run dev
脚手架运行预览
问题
这里直接访问 http://172.16.21.246:3000/
是不行的 有点击弹窗的信息进行访问, 如图
开启博客代码
配置 layout
<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">
<span class="mynav" @click="handleJump(item.route)">{{item.label}}</span>
</el-col>
</el-row>
</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 />
组件来展示其他页面内容。
脚本部分:
样式部分:
.nav
类定义导航栏整体的样式。
h1
标签设置了标题的样式,包括高度、光标类型以及行高等。
::v-deep .el-card__body
选择器通过::v-deep
关键词,使得内部样式可以影响该组件下的子组件,这里用来设置导航栏内部元素的样式。
.left
和.right
类分别设置了左侧和右侧区域的宽度和光标类型。
layout
部分的代码主要实现的是一个简单的导航栏组件,并使用 Nuxt 来展示其他页面内容。点击导航项会触发相应的跳转事件。
首页配置
<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>
<el-card class="box-card">
<clock />
</el-card>
</el-aside>
<el-main>
<el-card v-for="(item, index) in blogJson" :key="index">
<el-row :gutter="20">
<el-col :span="20" class="mycol">
<h3 @click="handleLink(item.blogLink)">{{ item.title }}</h3>
<p>{{ item.desc }}</p>
</el-col>
<el-col :span="4">
<el-image
style="width: 100px; height: 100px"
:src="item.imgLink"
fit="fill"
></el-image>
</el-col>
</el-row>
</el-card>
</el-main>
</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 的组件和样式进行展示。关于我部分展示了一张头像和一段文字信息,博客列表展示了多个博客项,每个博客项包括标题、描述和图片。点击博客标题会在新窗口中打开对应的博客链接。
其他页面
由于每个页面都有不同的用处, 这里就不做过多讲解说明, 对于这个博客感兴趣的朋友可以在文章最下面找到项目地址哦!
效果预览
项目目录结构
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 init2.git add .3.git commit -m '备注'4.git remote add origin git@gitee.com:shiqingqing/test.git5.git pull origin master6.开始上传 输入 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 脚本获取博客资源
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('css selector', 'h4')
title = title_elem.text
# 获取简介
desc_elem = article.find_element('css selector', '.blog-list-content')
desc = desc_elem.text
# 获取博客链接
link_elem = article.find_element('css selector', 'a')
link = link_elem.get_attribute('href')
# 将结果添加到列表中
result = {
'图片链接': img_src,
'标题': title,
'简介': desc,
'博客链接': 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 文件中')
复制代码
评论