菜鸟之路Day25一一前端工程化(二)
菜鸟之路Day25一一前端工程化(二)
作者:blue
时间:2025.3.19
文章目录
- 菜鸟之路Day25一一前端工程化(二)
- 1.概述
- 2.Element快速入门
- 3.综合案例
- 一.布局
- 二.组件
- 三.Axios异步加载数据
- 1. 生命周期钩子概述
- 2. `mounted` 钩子函数的作用
- 四.Vue路由
- 五.打包部署
1.概述
文章内容大部分学习自黑马程序员BV1m84y1w7Tb
本文延续上一篇菜鸟之路Day24一一前端工程化(一)-CSDN博客,旨在梳理,从0到1,在仅有一个vscode的情况下,一步步完成一个使用Vue框架搭建的前端页面,并最终将其部署在Nginx服务器上。
截至目前阶段,我们已经完成了Vue项目的创建,现在我们需要做的就是编写组件或者说是页面,然后最终将组件挂载到index.html中进行展示。我们一步步来完成这个过程。
2.Element快速入门
为了快速完成前端页面的编写,提高前端页面的编写效率,我们可以利用Element组件库来帮助我们完成这个工作
什么是Element?
Element:是饿了么团队研发的,一套作为开发者,设计师和产品经理准备的基于Vue2.0的桌面端组件库。
组件:组成网页部件,例如超链接,按钮,图片,表格,表单,分页条等等
官网:https://element.eleme.cn/#/zh-CNListener
环境配置
①安装ElementUI组件库(在当前工程的目录下),在命令行执行指令
npm install element-ui@2.15.3
②引入ElementUI组件库
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
完成以上两步后我们可以在src中的views文件夹中新建一个名为element的文件夹然后在这个文件夹下再创建一个ElementView.vue的组件文件,我们将在这个文件中对ElementUI库做一个简单的使用演示
我们可以访问Element的官网,然后在侧边栏中选择我们所需要的组件,查看其源码,然后进行一个复制粘贴
就如同以下代码,我复制了一串按钮组件的代码,直接粘贴到了template部分,有时我们复制的组件比较繁琐,还需要注意观察这个组件需不需要什么数据模型,或者是样式,要把他们都复制到对应的版块中。
<template>
<div>
<el-row>
<el-button>默认按钮</el-button>
<el-button type="primary">主要按钮</el-button>
<el-button type="success">成功按钮</el-button>
<el-button type="info">信息按钮</el-button>
<el-button type="warning">警告按钮</el-button>
<el-button type="danger">危险按钮</el-button>
</el-row>
</div>
</template>
<script>
</script>
<style>
</style>
一份简易的组件代码写好了,然后现在的问题是,我们要如何看见这个组件所展示的页面呢?
我们回顾,我们是怎么看到App.vue这个根组件所渲染的页面的,在mian.js中引入了App.vue,mian.js又将根组件挂载到index.html上,所以我们可以将ElementView.vue引入到App.vue这个根组件中。让ElementView.vue在App.vue中渲染。
具体怎么做呢?我们一步一步来看,首先如果读者是按照我上一篇文章跟进的话,那么此时App.vue中应该是有一个注册页面的代码,我们可以在views下新建一个文件夹,然后在这个文件夹新建一个login.vue组件,然后将刚刚App.vue中的代码移植过去,这样一来我们就清空了App.vue。
然后我们依然正常的在App.vue中写出一个.vue应该有的三个部分,template,script,style。好,别忘了我们的目的,是将ElementView.vue引入到App.vue这个根组件中。这个过程主要分为3步
①组件导入
在代码的 <script>
部分,我们使用 import
语句从指定路径导入 ElementView
组件:
import ElementView from "./views/element/ElementView.vue"
这一步的作用是将 ElementView.vue
文件中的组件定义引入到当前文件里,让当前文件可以使用该组件。
②局部组件注册
在 Vue 里,要使用一个组件,就需要先进行注册。在 components
选项里,键名 ElementView
是组件在当前组件中使用的名称,它的值就是之前导入的 ElementView
组件。Vue 会根据这个注册信息,在解析模板时识别并渲染对应的组件。
export default {
components: {
ElementView
},
// 其他选项
}
③模板中使用组件
在 <template>
部分,我们使用了 <element-view></element-view>
标签。在 Vue 中,组件名称在模板里使用时,既可以采用 PascalCase(大驼峰命名法,如 ElementView
),也可以使用 kebab-case(短横线分隔命名法,如 element-view
)。Vue 会自动把 element-view
映射到已注册的 ElementView
组件上,进而渲染出该组件的内容。
综上所述,因为我们导入了 ElementView
组件,并且在当前组件里进行了局部注册,所以能够在模板中使用 <element-view></element-view>
来渲染该组件。
于是App.vue中的代码被我们修改为了这样:
<template>
<div>
<!-- 3.在模板中使用组件 -->
<element-view></element-view>
</div>
</template>
<script>
//1.组件导入
import ElementView from "./views/element/ElementView.vue"
export default {
//2.局部组件注册
components: {
ElementView
},
}
</script>
<style>
</style>
此时我们再次启动这个项目,可以看到默认页面,已经变成了 ElementView.vue
中的内容
ElementUI库还有非常多的组件,使用方式与以上大同小异,再此就不一一展示。
3.综合案例
在这个综合案例中,我们将利用前面所学的知识完成一个综合小demo,并将其部署在Nginx服务器上。
步骤:
①创建页面,完成页面的整体布局规划
②布局中各个部分的组件实现
③列表数据的异步加载,并渲染展示
我们一步一步来做,首先,我在刚刚创建的User文件下创建了一个EmpView.vue,我们将在这个文件下将上面的内容编辑出来,我将其引入到App.vue中,这样我就能通过vue-cli提供的热部署功能,实时查看页面的编写情况。
一.布局
我们在Element官网发现以下这个布局非常适合我们
通过参考官网示例的代码,我们编写出大体布局的页面
EmpView.vue:
<template>
<div>
<el-container style="height: 700px; border: 1px solid #eee">
<el-header style="font-size: 40px; background-color: rgb(238, 241, 246)">智能学习辅助系统</el-header>
<el-container>
<el-aside width="200px">
<el-menu>
<el-submenu>
<template slot="title"><i class="el-icon-message"></i>信息管理系统</template>
<el-menu-item>部门管理</el-menu-item>
<el-menu-item>员工管理</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-main><el-table :data="tableData">
<el-table-column prop="name" label="姓名" width="180">
</el-table-column>
<el-table-column prop="image" label="图像" width="180">
</el-table-column>
<el-table-column prop="gender" label="性别" width="140">
</el-table-column>
<el-table-column prop="job" label="职位" width="140">
</el-table-column>
<el-table-column prop="entrydate" label="入职日期" width="180">
</el-table-column>
<el-table-column prop="updatetime" label="最后操作时间" width="230">
</el-table-column>
<el-table-column label="操作">
<el-button type="primary" size="mini">编辑</el-button>
<el-button type="danger" size="mini">删除</el-button>
</el-table-column>
</el-table></el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
data() {
return {
tableData:[]
}
}
}
</script>
<style>
</style>
针对一些属性的解释
prop
属性的作用是指定表格列要展示的数据字段。在表格渲染时,它会从每一行的数据对象里提取和prop
属性值同名的字段,然后将该字段的值显示在对应的表格单元格中。
placeholder
属性用于在输入框为空时显示一段提示性文本,它可以帮助用户了解该输入框期望输入的内容,起到引导用户输入的作用。当用户在输入框中输入内容时,这个提示文本会自动消失;而当输入框中的内容被清空后,提示文本又会重新显示出来。
二.组件
为页面添加必要组件,完善页面功能
<template>
<div>
<el-container style="height: 700px; border: 1px solid #eee">
<el-header style="font-size: 40px; background-color: rgb(238, 241, 246)">智能学习辅助系统</el-header>
<el-container>
<el-aside width="200px">
<el-menu>
<el-submenu>
<template slot="title"><i class="el-icon-message"></i>信息管理系统</template>
<el-menu-item>部门管理</el-menu-item>
<el-menu-item>员工管理</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-main>
<!-- 表单 -->
<el-form :inline="true" :model="searchFrom" class="demo-form-inline">
<el-form-item label="姓名">
<el-input v-model="searchFrom.name" placeholder="姓名"></el-input>
</el-form-item>
<el-form-item label="性别">
<el-select v-model="searchFrom.gender" placeholder="性别">
<el-option label="男" value="1"></el-option>
<el-option label="女" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="入职日期">
<!-- 日期选择器 -->
<el-date-picker v-model="searchFrom.entrydate" type="daterange" range-separator="至"
start-placeholder="开始日期" end-placeholder="结束日期">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
<!-- 表格 -->
<el-table :data="tableData" border>
<el-table-column prop="name" label="姓名" width="180">
</el-table-column>
<el-table-column prop="image" label="图像" width="180">
</el-table-column>
<el-table-column prop="gender" label="性别" width="140">
</el-table-column>
<el-table-column prop="job" label="职位" width="140">
</el-table-column>
<el-table-column prop="entrydate" label="入职日期" width="180">
</el-table-column>
<el-table-column prop="updatetime" label="最后操作时间" width="230">
</el-table-column>
<el-table-column label="操作">
<el-button type="primary" size="mini">编辑</el-button>
<el-button type="danger" size="mini">删除</el-button>
</el-table-column>
</el-table>
<br>
<!-- 分页条 -->
<el-pagination background layout="prev, pager, next" :total="1000">
</el-pagination>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [],
searchFrom: {
name: "",
gender: "",
entrydate: []
}
}
},
methods: {
onSubmit() {
alert("submit!");
}
}
}
</script>
<style>
</style>
三.Axios异步加载数据
在Vue项目中使用Axios:
//在项目目录下安装axios:npm insatll axios
//需要使用axios时,导入axios:import axios from 'axios'
请求代码:
<script>
import axios from 'axios'
export default {
data() {
return {
tableData: [],
searchFrom: {
name: "",
gender: "",
entrydate: []
}
}
},
methods: {
onSubmit() {
alert("submit!");
}
},
mounted() {
axios.get('http://127.0.0.1:4523/m1/6068388-5758637-default/user/1')
.then(result => {
console.log(result.data.data); // 打印返回的数据,检查格式
// console.log('数据类型:', Array.isArray(result.data.data));
this.tableData = [result.data.data]; //魔鬼细节!!!
})
.catch(error => {
console.error('请求出错:', error);
});
}
}
</script>
注意注意,这里有一个魔鬼细节,笔者在这里调试35min才调试出来(deepseek NB)
this.tableData = [result.data.data]; //魔鬼细节!!!
由于tableData所需要的数据是一个数组,但是result.data.data是一个对象,所以,我们应该把result.data.data强行转为一个数组。
不过这不太优雅,这是接口的问题,接口的响应数据应该是一个对象数组,所以我们可以直接去改接口
最终我们将接口的数据结构修改为如下图所示
这样我们就可以直接做一个赋值操作啦this.tableData = result.data.data;
<template>
<div>
<el-container style="height: 700px; border: 1px solid #eee">
<el-header style="font-size: 40px; background-color: rgb(238, 241, 246)">智能学习辅助系统</el-header>
<el-container>
<el-aside width="200px">
<el-menu>
<el-submenu>
<template slot="title"><i class="el-icon-message"></i>信息管理系统</template>
<el-menu-item>部门管理</el-menu-item>
<el-menu-item>员工管理</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-main>
<!-- 表单 -->
<el-form :inline="true" :model="searchFrom" class="demo-form-inline">
<el-form-item label="姓名">
<el-input v-model="searchFrom.name" placeholder="姓名"></el-input>
</el-form-item>
<el-form-item label="性别">
<el-select v-model="searchFrom.gender" placeholder="性别">
<el-option label="男" value="1"></el-option>
<el-option label="女" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="入职日期">
<!-- 日期选择器 -->
<el-date-picker v-model="searchFrom.entrydate" type="daterange" range-separator="至"
start-placeholder="开始日期" end-placeholder="结束日期">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
<!-- 表格 -->
<el-table :data="tableData" border>
<el-table-column prop="id" label="ID" width="180">
</el-table-column>
<el-table-column prop="name" label="姓名" width="180">
</el-table-column>
<el-table-column prop="image" label="图像" width="180">
</el-table-column>
<el-table-column prop="gender" label="性别" width="140">
</el-table-column>
<el-table-column prop="job" label="职位" width="140">
</el-table-column>
<el-table-column prop="entrydate" label="入职日期" width="180">
</el-table-column>
<el-table-column prop="updatetime" label="最后操作时间" width="230">
</el-table-column>
<el-table-column label="操作">
<el-button type="primary" size="mini">编辑</el-button>
<el-button type="danger" size="mini">删除</el-button>
</el-table-column>
</el-table>
<br>
<!-- 分页条 -->
<el-pagination background layout="prev, pager, next" :total="1000">
</el-pagination>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
tableData: [],
searchFrom: {
name: "",
gender: "",
entrydate: []
}
}
},
methods: {
onSubmit() {
alert("submit!");
}
},
mounted() {
axios.get('http://127.0.0.1:4523/m1/6068388-5758637-default/user/1')
.then(result => {
console.log(result.data.data); // 打印返回的数据,检查格式
// console.log('数据类型:', Array.isArray(result.data.data));
this.tableData = result.data.data;
})
.catch(error => {
console.error('请求出错:', error);
});
}
}
</script>
<style>
</style>
在此需要解释一下mounted钩子函数
在 Vue.js 中,mounted
是一个生命周期钩子函数。下面为你详细介绍 mounted
钩子函数的相关内容:
1. 生命周期钩子概述
Vue 实例从创建到销毁的整个过程,被称为 Vue 的生命周期。在这个生命周期的不同阶段,Vue 会自动调用一些特定的函数,这些函数就被叫做生命周期钩子函数。开发者可以利用这些钩子函数,在特定的时间点执行自定义的逻辑。
2. mounted
钩子函数的作用
mounted
钩子函数会在 Vue 实例挂载到 DOM 之后立即被调用。也就是说,当 Vue 实例已经将其模板渲染成真实的 DOM 元素并插入到页面中时,mounted
函数就会执行。通常,我们会在这个钩子函数里进行一些需要访问 DOM 的操作,或者发起异步请求来获取数据。
可以看到数据成功被渲染
四.Vue路由
我们可以看到,我们在浏览器中打开项目,他的URL是这样的
http://localhost:7000/#/
前端路由:URL中的hash{#号}与组件之间的对应关系
Vue Router 是Vue的官方路由
组成:
VueRouter:路由器类,根据路由请求在路由视图中动态渲染选中的组件
‘’ :请求链接组件,浏览器会解析成’’
‘’:动态视图组件,用来渲染展示与路由路径对应的组件
我们可以通过配置路由来完成页面的切换
首先要注意安装Vue Router(不过我们在用ui界面创建Vue项目时已经选择了)
npm install vue-router@3.5.1
如何配置路由信息呢?
在src>router>index.js中可以配置路由信息,我们可以看到官方的Vue项目给我们演示了两种配置路由的方法,我们只需要依葫芦画瓢进根据我们的需要进行修改即可,因为我们之前写了注册界面,所以我在这里就做一个注册界面与员工管理界面切换的演示逻辑,并不符合正常业务逻辑,仅仅只是为了展示。
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
]
const router = new VueRouter({
routes
})
export default router
path
:表示路由的路径,这里的'/'
是根路径,当用户访问应用的根 URL 时,会匹配到这个路由。name
:为路由定义的一个名称,这里是'home'
,可以在代码中通过名称来引用这个路由,例如在使用router.push
或router-link
时可以使用名称来导航,这样可以提高代码的可读性和可维护性。component
:指定当用户访问该路径时要渲染的组件,这里直接引用了HomeView
组件,意味着在项目中已经导入了HomeView
组件。
about这里使用了动态导入(也称为懒加载)的方式来加载组件。具体解释如下:
() => import('../views/AboutView.vue')
是一个箭头函数,返回一个import()
函数调用。import()
是 ES6 动态导入模块的语法,它会返回一个 Promise,当 Promise 成功解析时,会加载并返回指定的模块。
我们将src>router>index.js修改成这样
const routes = [
{
path: '/Emp',
name: 'Emp',
component: () => import( '../views/User/EmpView.vue')
},
{
path: '/login',
name: 'login',
component: () => import('../views/User/loginView.vue')
}
]
然后我们’'来链接组件
EmpView.vue中
<el-submenu>
<template slot="title"><i class="el-icon-message"></i>信息管理系统</template>
<el-menu-item><router-link to="/login">登录</router-link></el-menu-item>
<el-menu-item><router-link to="/Emp">员工管理</router-link></el-menu-item>
</el-submenu>
这个改好之后我们通过’'来渲染组件,在根组件App.vue中,将原来挂载的组件信息注释掉用动态视图组件,来渲染展示与路由路径对应的组件
<template>
<div>
<!-- 3.在模板中使用组件 -->
<!-- <EmpView></EmpView> -->
<router-view></router-view>
</div>
</template>
<script>
//1.组件导入
// import EmpView from './views/User/EmpView.vue'
export default {
//2.局部组件注册
components: {
// EmpView
},
}
</script>
<style>
</style>
此外,为了避免打开根目录时出现空白页面,我们对根目录的路由做一个重定向
const routes = [
{
path: '/Emp',
name: 'Emp',
component: () => import( '../views/User/EmpView.vue')
},
{
path: '/login',
name: 'login',
component: () => import('../views/User/loginView.vue')
},
//将根目录重定向到login页面
{
path: '/',
redirect: '/login'
}
]
好了路由配置到这里就结束了,我们重新启动项目,现在,我们可以自由切换页面了
五.打包部署
打包
打包只需要执行build任务就可以了,打包后的内容会被放在dist文件夹下,我们做部署的话,就只需要将dist内容部署到服务器上即可。
npm run build
部署
Nginx
介绍:Nginx是一款轻量级的web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少,并发能力强。
下载地址:nginx: download
解压后,文件中有这么几个文件。
部署:将打包好的dist目录下的文件按,复制到nginx安装目录的html目录下
启动:双击nginx.exe文件即可,Nginx服务器默认占用80端口号
直接在浏览器访问80端口,即可访问,我们刚刚所写的页面
访问:http://localhost:90
如果80端口被占用了,可以在conf文件夹下的nginx.conf文件中修改默认的端口号
打开后,修改server板块下的listen即可