综合实训
本次笔记主要是在做前端项目的时候涉及前端的一些基础知识,主要包括以下内容
git技能总结
安装教程
下载地址:https://npm.taobao.org/mirrors/git-for-windows/
参考教程https://gitee.com/niit-cs/computational-thinking#/niit-cs/computational-thinking/blob/master/labs/test/test.md
开始教程
1,右键打开Git Bash,输入如下命令,配置git操作的用户名、邮箱。
$ git config --global user.name "你的名字或昵称"
$ git config --global user.email "你的邮箱"
2,配置ssh公钥
在Git Bash中输入如下命令,生成SSH key。
$ ssh-keygen -t rsa -C "你的邮箱"
3,输入如下第1行命令,打印刚才生成的SSH key
$ cat ~/.ssh/id_rsa.pub
4,主页右上角 「个人设置」->「安全设置」->「SSH公钥」->「添加公钥」 ,复制生成的 public key,添加到当前账户中。
5,测试SSH key是否配置ok:
$ ssh -T git@gitee.com
Hi 朱家乐! You've successfully authenticated, but GITEE.COM does not provide shell access.
上传文件
注意不要删除
$ git add . #将当前目录所有文件添加到git暂存区
$ git commit -m "my commit" #提交并备注提交信息
$ git push #将本地提交推送到远程仓库
下载文件
打开==自己账号==下的仓库,点击 “克隆/下载” 按钮,选择 “SSH”, 点击“复制”
$ git clone git@gitee.com
本地更新别人上传的文件
git pull
(在gitee网页上看到修改状态)
修改时保证最新版,git pull下来保证最新版,在git push
在任何时候,你本地在提交代码(git push)之前,请都需要先git pull拉取服务器最新代码,以免冲突!
视频资源汇总
- https://learngitbranching.js.org/ git语句练习平台 — 适用于全体同学
- https://docs.oracle.com/javase/8/docs/api/index.html java开发文档,不建议全文阅读,建议阅读重点类,如ArrayList, HashMap等 — 适用于后端开发同学
- https://www.iconfont.cn/home/index 前端资源,如字体、icon等 — 适用于前端开发同学
- https://www.imooc.com/learn/945 springboot、mybatis、mysql的使用(只看前3章就可以) — 适用于后端开发同学
- https://www.bilibili.com/video/BV1AT4y1w7pH vue基础 — 适用于前端开发同学
- https://blog.youkuaiyun.com/weixin_45295447/article/details/124825881 接口mock教程 — 适用于前端开发同学
- https://blog.youkuaiyun.com/weixin_58448088/article/details/123187457 git安装和使用
搜索和高级搜索页面编写进程
select.vue和selectheight.vue
点击搜索逻辑的设计,调试可行**this.isShow
用于控制组件的显示与隐藏**
<div class="table" v-if="isShow">
<table v-if="studentInfo?.length">
<thead>
<tr>
<th>姓名</th>
<th>学号</th>
<th>班级</th>
<th>专业</th>
<th>类型</th>
</tr>
</thead>
<tbody>
<tr class="student-list" @click="toDetail(student.stuId)" v-for="(student, index) in studentInfo"
:key="index">
<td>{{ student.stuName }}</td>
<td>{{ student.stuId }}</td>
<td>{{ student.classNum }}</td>
<td>{{ student.major }}</td>
<td>{{ student.eduType }}</td>
</tr>
</tbody>
<!-- 分页 -->
<el-pagination small layout="prev, pager, next" :total="105" :page-size="10"
@current-change="changeSize($event)"></el-pagination>
</table>
</div>
- 使用
v-if
判断studentInfo
数组是否存在,如果存在则渲染表格,否则不渲染。 <table>
标签表示表格,包含表头和表体。<thead>
标签表示表头,包含一个表格行。<tr>
标签表示表格行,包含多个表格单元格。<th>
标签表示表格头部单元格,即列标题。这里包括“姓名”、“学号”、“班级”、“专业”和“类型”五个列标题
其中包含多个表格行<tr>
,每个表格行代表了一个学生信息。通过v-for
指令,使用studentInfo
数组中的每个元素创建一个表格行。在每个表格行中,使用双大括号语法{{}}
来插入对应学生的信息,例如{{ student.stuName }}
会显示该学生的姓名。@click
绑定了一个点击事件,当用户点击表格行时,会调用toDetail()
方法,并将该学生的stuId
作为参数传递给该方法。<tbody>
表示表格的主体部分。
点击select方法后的事件处理
select(event, pageNum = 1, pageSize = 10) {
this.isShow = true
this.$http
.post(
`/api/student/search`, {
stuName: this.searchValue,
pageNum,
pageSize, } )
事件处理函数,当用户触发了“查询”按钮的点击事件时,会执行该函数。该函数首先将Vue实例的isShow属性设置为true,表示正在进行查询。然后,使用Vue实例的$http对象向指定的后端API发送一个POST请求。请求体中包含了查询条件,即stuName
(学生姓名)、pageNum
(页码)和pageSize
(每页数据数量)
在请求完成后,根据API的返回结果更新Vue实例的studentInfo属性。具体地,如果返回的状态码是200,则将响应数据中的data.data
赋值给studentInfo属性。如果请求失败,则在控制台中打印出错误信息
使用同样的方法编写高级搜索的界面,唯一区别是在搜索条件做了相应的改变
.post(
`/api/student/search`,
{
stuName: this.stu_name,
stuId: this.stu_id ? Number(this.stu_id) : '',
classNum: this.class_num,
pageNum,
pageSize,
}
)
顶栏组件header.vue以及index.vue的编写
顶栏设计一个路由跳转,
<div class="logo">
<img src="../assets/home.png" class="img" @click="handleTo" />
</div>
在父组件调用的时候,代码编写
<template>
<Header></Header>
<Detail :studentInfo="studentInfo"></Detail>
</template>
导航点击选择跳转不用的页面
<el-tabs v-model="activeName" stretch @tab-change="handleClick">
<el-tab-pane label="个人信息" name="A"></el-tab-pane>
<el-tab-pane label="学习科研" name="B"></el-tab-pane>
<el-tab-pane label="奖惩助贷" name="C"></el-tab-pane>
<el-tab-pane label="第二课堂" name="D"></el-tab-pane>
<el-tab-pane label="书院信息" name="E"></el-tab-pane>
</el-tabs>
<div class="container">
<PersonInfo :studentInfo="studentInfo" v-if="activeName === 'A'"></PersonInfo>
<Research v-if="activeName === 'B'"></Research>
<RewardsPunishment v-if="activeName === 'C'"></RewardsPunishment>
<secondclass v-if="activeName === 'D'"></secondclass>
<college v-if="activeName === 'E'"></college>
<div v-if="activeName === 'D'"></div>
</div>
学生头像页面信息的编写
主要是涉及了一个预警显示,调用tag组件,通过v-if来判断是非显示预警模块,这个逻辑还挺简单的
<el-tag effect="dark" size="large"> 在校 </el-tag>
<el-tag style="background-color: red;" effect="dark" size="large" v-if="studentInfo?.bedWarn === '归寝预警'">
归寝预警
</el-tag>
<el-tag style="background-color: red;" effect="dark" size="large" v-if="studentInfo?.studyWarn === '学业预警'">
学业预警
</el-tag>
同时主要注意的是,父组件和子组件之间的数据传输 异步函数getStudentInfo’,onUpdated
钩子函数:生命周期钩子函数
tab1个人信息页面person.vue
这个界面的编写还挺简单的,难点在于父亲母亲这个icon头像的调用遇到了一些问题,写一个模块调用不同的assets图片
在这里耗了挺长的时间的
// 先定义这个assetsUrl基本路径
const assetsUrl = ref('../../../src/assets/')
const parentInfo = ref([
{
// avatar:size="64",src "female",
// avatar: require('..src/assets/avatar15.png'),
avatar:
`${assetsUrl.value}dad.png`,//调用资源图库
name: 'zhangba',
role: '父亲',
workUnit: 'A单位',
job: 'A工作',
phone: 15551232333,
},
{
avatar:
`${assetsUrl.value}mom.png`,
name: 'zhangma',
role: '母亲',
workUnit: 'B单位',
job: 'B工作',
phone: 15231232333,
},
])
tab2-学习科研research.vue
1.一开始没有写分页器,之后直接没有把后端的pagesize和pagetotal传进去,显示有些异常
2.第二个问题是,分页器传参的时候每页显示45行,但是因为样式的问题列表没有显示全,加了一个min-height参数控制样式
<el-pagination small layout="prev, pager, next" :total="courseTotal" :page-size="coursePage.pageSize"
@current-change="changeSize($event, 'o')"></el-pagination>
//因为这个页面有两个表,所以changesize这个方法用0这个数来控制是哪个表的值
<el-card class="box-card" style="min-height: 200px">
<el-table :data="tableDataDeep" border stripe style="width: 100%">
<el-table-column prop="coachTime" label="辅导时间" width="180" />
<el-table-column prop="coachPerson" label="辅导人" width="180" />
<el-table-column prop="coachDetails" label="辅导详情" />
</el-table>
</el-card>
科研创新的图和上一个tab的界面,通过下面的代码就可以调用不同的图片
const assetsUrl = ref('../../../src/assets/')
const scientificList = ref([
{ icon: `${assetsUrl.value}res1.png`, text: '论文', count: 2, unit: '篇', color: 'red' },
{ icon: `${assetsUrl.value}res2.png`, text: '著作', count: 2, unit: '部', color: 'green' },
{ icon: `${assetsUrl.value}res3.png`, text: '专利', count: 2, unit: '篇', color: 'blue' },
{ icon: `${assetsUrl.value}res4.png`, text: '软著', count: 2, unit: '部', color: 'green' },
])
tab3-RewardsPunishment.vue奖惩助贷界面
涉及到一个柱状图的绘制,一文快速上手Echarts
function drawChart() {
const chartContainer = document.getElementById('myChart')
const chart = echarts.init(chartContainer)
chart.setOption({
title: {
test: 'test', },
xAxis: { type: 'category',
data: [
'一月',
'二月',
'三月',
'四月',
'五月',
'六月',
'七月',
'八月',
'九月',
'十月',
'十一月',
'十二月',
],
},
yAxis: {
type: 'value',
},
series: [
{
data: workStudyInfo.value.stat,
type: 'bar',
},
],
})
}
tab4和tab5的柱状图和饼图也有涉及,在画了tab3的柱状图之后,给另一个小伙伴画这两图还挺easy的,有点开心,嘿嘿
附上饼图的代码
function drawChart(data) {
console.log(data)
const chartContainer = document.getElementById('myChart')
const chart = echarts.init(chartContainer)
chart.setOption({
title: {
left: 'center',
},
tooltip: {
trigger: 'item',
},
legend: {
orient: 'vertical',
left: 'left',
},
series: [
{
name: 'Access From',
type: 'pie',
radius: '50%',
data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
},
],
})
}
接口封装
一开始我是直接用axios写接口,老师说接口比较繁琐的画,会很麻烦,建议将接口封装
自己模仿写的封装接口
request.js,主要是一些拦截器配置,这没啥好说的
import axios from 'axios'
//配置基地址
const service = axios.create({
baseURL: 'http://localhost:8088/',
timeout: 10000
})
service.interceptors.request.use(
(config) => {
return config
},
(error) => {
return Promise.reject(error)
}
)
service.interceptors.response.use(
(response) => {
return response
},
(error) => {
return Promise.reject(error)
}
)
export default service
项目主要接口student.js部分接口展示
// <!-- ---------------------------Tab4 <第二课堂>------------------------------------- --!>
// 1活动成长
export function getActivity(data) {
return request({
url: "/second/activity",
data,
method: "post",
})
}
// 2深度辅导
export function getdeepCoach(data) {
return request({
url: "/second/deepCoach",
data,
method: "post",
})
}
可以和之前没有封装的进行比较axios请求,请求学生数据的请求如下
select(event, pageNum = 1, pageSize = 10) {
this.isShow = true
this.$http
.post(`http://localhost:8088/student/search`, {
stuName: this.searchValue,
pageNum,
pageSize,
})
.then(
(response) => {
const { data: res } = response
if (res.code == 200) {
this.studentInfo = res.data.data
}
},
(err) => {
return err
}
)
},
基础功能联调
5个tab界面的数据联调,tab4和tab5不是我写的,感觉不是很熟悉,并且只写了css和html内容,vue基本没写js内容,配起来还得写一些响应式定义数据,停耗费时间的,感觉应该在小伙伴在写这两页面的时候就应该对接好,让他连着把一些js的定义也写好,这样我对接口的话比较方便,团队协作没协调好
使用postman,查看接口数据返回,一开始不熟悉以及忘记看接口文档的参数了,配起来不是很顺利,之后就很顺利的,以下是需要特别注意的点,有些测试文档传参除了stuId还有type,以及特别注意的点就是post请求时,在body传参时//不表示注释,会导致badrequest
F12调出开发者模式,可以看页面的返回数据这一点也很有帮助
- 封装接口的时候get传参需要用params,post传参直接写data就好
- get调用的时候写 需要传参的{键值对} 就可以传参成功啦,post调用的时候就是 直接写你要传的参数
例子,用post和get方法来请求学生信息的写法区别
//get方法
export function getStudentInfo(id) {
return service({
url: '/student/info',
method: 'get',
params: {
stuId: id
}
})
}
//post方法
export function getStudentInfo(id) {
return service({
url: '/student/info',
method: 'post',
data: {
stuId: id
}
})
}
使用了axios的post方法来发送POST请求,请求体中携带了一个名为stuId的参数,参数值为传入的id参数。注意,请求体中使用data来设置参数
GET请求不包含请求体,参数会以键值对的形式附加在URL的末尾,可以直接在浏览器地址栏中看到。
而POST请求通常需要一个请求体,将参数包含在请求体中进行传递
假设我们要向服务器发送一个查询学生信息的请求,请求参数为学生的学号。使用GET请求,我们可以将请求参数以键值对的形式附加在URL的末尾,比如:
http://example.com/api/student?studentId=12345
GET请求没有请求体,所有的参数都以查询字符串的形式附加在URL的末尾,因此,GET请求不适合传输大量数据或敏感数据,因为URL中的参数可以被拦截、修改或者缓存。
例如:
http://example.com/path?key1=value1&key2=value2
。
在浏览器中访问这个URL,可以直接看到请求参数。而使用POST请求,我们需要在请求体中包含参数,比如:
POST http://example.com/api/student HTTP/1.1
Content-Type: application/json
{"studentId": 12345}
这个请求中,请求参数是以JSON格式的字符串放在请求体中的。因为请求体不会直接在URL中暴露,所以POST请求比GET请求更适合传输一些敏感的数据,比如密码等
动态路由跳转信息和前端渲染功能
通俗来说就是,http://localhost:8000/student-detail/21213333
这个就是学生id,每个学生的id是唯一,那我们可以根据id来实现动态路由,当我们进入到学生详情页的时候,调用后端的api,因为后端的这些信息,会根据学生的id不用,返回不同的数据,前端再渲染就可以。
那这种情况,我们不可能写很多组件来渲染,因为他们只是数据不一样,页面ui是一样的,那就用到了动态路由
前后端跨域代理有误
最后写了一个代理,但是发现后端也写了,在前端请求url的时候稀里糊涂用了一点代理,但是封装的api请求大多都是走的后端跨域解决,一开始不是很懂,只晓得写一个代理在那,现在回过头才发现没咋用上我写的代理,笑死了
跨域含义以及原因
不同域名、不同端口或不同协议
浏览器只允许 JavaScript 代码与同源(相同协议、域名和端口)的资源进行交互,而不允许与不同源的资源进行直接交互
跨域问题是指在浏览器中,当一个网页的 JavaScript 代码尝试访问不同域名、不同端口或不同协议的资源时所遇到的安全限制。浏览器出于安全考虑,限制了跨域访问的能力,以防止恶意网站通过 JavaScript 代码访问其他域上的敏感信息或进行恶意操作
解决跨域
代理服务器:可以通过在自己的服务器上设置代理服务器来解决跨域问题。前端代码向自己的服务器发送请求,然后服务器再将请求转发到目标域上,获取响应后再返回给前端。由于浏览器与服务器之间的请求是同域的,因此可以绕过跨域限制修改后
vite.config
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
//'@': fileURLToPath(new URL('./src', import.meta.url)):将别名 @ 设置为 ./src 目录的绝对路径。这是为了在项目//中///使用 @ 符号来引用项目的根目录
server: {
host: 'localhost',
port: 8000,
proxy: {
'/api': {
target: 'http://localhost:8088',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
//:设置一个代理规则,当请求路径以 /api 开头时,会被代理到目标服务器。
},
},
}
})
当前端代码发起以 /api
开头的请求时,Vite 服务器会将请求转发到 http://localhost:8088
目标服务器上,并将响应返回给前端,从而解决了跨域问题。这样前端代码就可以通过访问相对路径 /api
来与后端进行跨域通信
头像上传操作
静态的图片命名和数据学号动态绑定,重点在于动态刷新,异步请求以及onupdated在数据更新时执行一次复制
(数据是从父组件index.vue传过来的)在子组件detail.vue上,在组件挂载后和更新后,根据 props.studentInfo
的值动态更新 detail.circleUrl
的路径。这个路径用于引用学生的圆形头像图片,并通过绑定到模板中的元素来显示图片
// assetsUrl路径
const assetsUrl = ref('../../../src/assets/')
onMounted(() => {
console.log("123===>", props.studentInfo)})
onUpdated(() => {
detail.circleUrl = `${assetsUrl.value}${props.studentInfo.stuId}.png`
})
const detail = reactive({circleUrl: ''})
assetsUrl
变量:这是一个响应式引用(ref),它的初始值是'../../../src/assets/'
。它表示了一个路径,用于引用组件中的静态资源(例如图片)的根目录。onMounted
钩子函数:生命周期钩子函数。它在组件挂载到 DOM 后立即执行。在这个函数中,会输出日志信息"123===>"
,并打印props.studentInfo
的值。props
是组件的属性对象,studentInfo
是其中一个属性。onUpdated
钩子函数:生命周期钩子函数。它在组件的更新周期中被调用。在这个函数中,会更新detail.circleUrl
的值。detail
是一个使用reactive
函数创建的响应式对象,它包含一个属性circleUrl
,初始值为空字符串。detail.circleUrl
的赋值:在onUpdated
钩子函数中,detail.circleUrl
的值被设置为${assetsUrl.value}${props.studentInfo.stuId}.png
。这里使用了assetsUrl.value
来获取assetsUrl
变量的值,然后将props.studentInfo.stuId
拼接在路径的末尾,并加上.png
扩展名,最终得到一个完整的 URL。这个 URL 用于引用特定学生的圆形头像图片。
涉及到这个异步函数getStudentInfo’,
const getStudentInfoImpl = async () => {
const res = await getStudentInfo(route.params.id)
studentInfo.value = res.data.data
console.log("res", studentInfo)
}
异步函数 getStudentInfo
,获取学生信息并将其保存到名为 studentInfo
的响应式对象中。然后,通过打印日志来确认获取的学生信息的值。这可能是一个用于获取特定学生信息的请求,并将结果更新到组件中的数据对象中,以便在模板中使用或进行其他操作
起后端联调步骤
后端程序的正确起发:
IDE文件open然后点那个pom文件,以打开文件夹的形式,打开,之后settings配置,之后apply就会有那个运行的接口了!
前端文件源码的大致分配,项目文件具体介绍
在Vscode
项目终端根目录键入npm list vue
可查看自己是vue2还是vue3,例如,我是vue3项目
package.json项目依赖的一个依赖包,可以看到这个项目的版本号,以及是否公开,重点看scripts这个文件下的东西,比如dev就可以用npm run dev运行并打开
main.js是这个项目的一个入口,app.vue是项目的一个模块化的根模块,views是放所有的页面,store是一个全局状态管理,router
使用组件elementplus组件或者vant组件
项目技术栈
Vue全家桶:Vue+Vue router + Vuex +Axios +ElementUI
安装依赖:
1.网络请求npm install --save axios
2.ElementUI vue add element
3.安装路由router npm install vue-router
vue-cli和vue有什么区别?
“vue-cli”和vue的区别:vue是“vue.js”的简称,是一个成熟的用于构建用户界面的JavaScript渐进式框架,而“vue-cli”是vue基础上进行开发的工具系统,是vue框架的一个命令工具。
# 全局安装 vue - cli
npm install - g @vue / cli
# 查看vue - cli的版本, 检验vue - cli是否安装成功
vue--version
前端的每一个界面都可以写在views下面,新建一个后缀名为vue的文件,在文件里键入vue回车即可快速新建一个vue文件,其次如果一个页面下有多个界面,比如首页这种界面,点击不同的界面会出来多种界面,则可以再view下面新建一个文件夹main,然后把这个单个界面所包含的所有界面全部放在里面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9k37oDB9-1684308951600)(E:\Coding\typora\综合实训\image-20230403114731025.png)]
路由router文件下的js文件代码如下
import Vue from 'vue'
import Router from 'vue-router'
Vue.useAttrs(Router)
const routes = [
{ path: '/',component: () => import('../components/a.vue') },
{ path: '/',component: () => import('../components/b.vue') },
]
const router = new Router({
routes
})
export defaut router
这里涉及到在main.js文件中代码的创建实例时,vue2和vue3的区别
/*vue2 的写法,在Vue 2中,创建Vue实例时,可以传递一个选项对象,该对象中可以包含一个 render 函数,用于渲染Vue应用程序的根组件,以及一个 router 实例,用于管理应用程序的路由。
在Vue 2中,使用 $mount 方法手动挂载Vue实例到DOM元素上,该方法接受一个CSS选择器作为参数,用于指定DOM元素的位置。
*/
import App from './App.vue'
import list from './index'
Vue.use(list)
import router from './router/index.js'
Vue.config.productionTip = false
new Vue({
render:h => h(APP),
router
}).$mount('#app')
/*在Vue 3中,创建Vue实例的方式已经发生了变化,new Vue 不再被支持。Vue 3提供了一个 createApp 方法,用于创建Vue应用程序实例。此外,Vue 3中的 render 函数也有所不同,并且不再需要手动调用 $mount 方法来挂载Vue实例。*/
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
//上述代码改成vue3的写法应该时如下所示:
import { createRouter, createWebHashHistory } from 'vue-router';
import A from '../components/a.vue';
import B from '../components/b.vue';
const routes = [
{ path: '/', component: A },
{ path: '/b', component: B },
];
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export default router;
main.js代码如下:
//vue3
import { createApp } from 'vue'
import App from './App.vue'
import list from './index'
import router from './router/index.js'
import './assets/main.css'
const app = createApp(App)
app.use(list)
app.use(router)
app.mount('#app')
//vue2
import { createApp } from 'vue'
import App from './App.vue'
import list from './index'
Vue.use(list)
import router from './router/index.js'
Vue.config.productionTip = false
new Vue({
render:h => h(APP),
router
}).$mount('#app')
import './assets/main.css'
createApp(App).mount('#app')
main.js代码的vue2VS3的区别
vue2模块下的代码
import vue from 'vue'
import App from './App'
import router from './router'
new Vue({
el:'#app',
router,
render: h = > h(App)
})
改成vue3的写法
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App)
.use(router)
.mount('#app')
注意以下几点改动:
vue
库变成了vue
的package
包,需要使用 ES6 的模块化引入方式。render
函数变成了模板template
,可以直接使用.vue
文件的方式来定义模板。new Vue()
变成了createApp()
方法。el
属性被移除了,需要使用mount()
方法来挂载实例。另外,如果你在
App.vue
中使用了template
标签来定义模板,也需要将其改为单文件组件的写法,即将template
标签内容直接写在.vue
文件的<template>
标签中
vue项目运行流程
具体可详情查看这篇博客,Vue项目启动代码执行流程分析
这篇主要介绍整个流程是干嘛的,每个命令主要讲了什么内容[Vue运行流程]([(38条消息) Vue运行流程_vue项目运行流程_qq_45436798的博客-优快云博客](https://blog.youkuaiyun.com/qq_45436798/article/details/109400503#:~:text=Vue运行流程 1 控制台输入 npm run dev,在执行命令时,会自动寻找 package.json 文件,package.json,App.vue 6 读取route 下的index.js 7 加载至 HelloWorld.vue 页面显示内容))
index.html–>main.js->app-vue -->router/index.js(路由)–>Helloword.vue
1.控制台输入 npm run dev
,在执行命令时,会自动寻找 package.json 文件,package.json 包含项目的名称版本、项目依赖等相关信息!
main.js文件到APP.vue代码的运行过程
在 Vue.js 应用程序中,main.js
文件是应用程序的入口文件,它负责初始化 Vue.js 实例,并将其挂载到特定的 DOM 元素上。
在 main.js
文件中,我们通常会创建一个 Vue.js 实例,并使用 render
函数或模板来渲染根组件(通常是 App.vue
组件)。当 Vue.js 实例被创建并且挂载到 DOM 上后,Vue.js 就会自动解析 App.vue
组件中的模板,并将其渲染到挂载的 DOM 元素上。
具体来说,main.js
文件一般会包含以下代码:
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount('#app')
在上面的代码中,我们使用 createApp
函数创建一个 Vue.js 实例,并将 App.vue
组件作为根组件传递给它。接着,我们使用 app.mount('#app')
方法将 Vue.js 实例挂载到 id
为 app
的 DOM 元素上,这样 Vue.js 就能够自动渲染 App.vue
组件中的内容了。在 App.vue
组件中,我们可以使用 template
或 render
函数来定义组件的内容。当 Vue.js 实例被挂载到 DOM 上后,Vue.js 会自动解析 App.vue
组件中的模板,并将其渲染到挂载的 DOM 元素上。
App.vue调用单独其他组件的一个过程
App.vue
是Vue
应用的根组件,它是Vue
组件中最顶层的一个组件,负责组装其他的子组件,提供整个应用的布局和样式。在一个
Vue
应用中,通常会将App.vue
组件作为整个应用的入口组件,它会作为整个页面的最外层容器,负责渲染其他组件,并提供应用所需要的共享资源,例如路由、状态管理、全局样式等。
App.vue
组件通常由三部分组成:
- 模板(template):负责组装其他子组件,并定义整个应用的布局和结构。
- 脚本(script):提供组件的逻辑和行为,例如事件处理、数据处理等。
- 样式(style):定义组件的样式,例如布局、颜色、字体等。
在一个
Vue
应用中,App.vue
组件的作用非常重要,它通常承担着整个应用的核心职责。在该组件中,我们可以定义应用的整体结构和样式,包括导航栏、页脚、页面布局等,从而实现整个应用的视觉效果和交互体验。
在 Vue.js 应用程序中,组件可以通过 import
语句来引入其他组件,从而实现组件之间的通信和交互。具体来说,假设你有一个名为 HelloWorld.vue
的组件,它的代码如下所示:
<template>
<div>
<h1>Hello, World!</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld'
}
</script>
要在 App.vue
组件中引用 HelloWorld.vue
组件,可以使用 import
语句来引入 HelloWorld.vue
组件,并将其注册为 App.vue
组件的子组件,如下所示:
<template>
<div>
<HelloWorld />
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
在上面的代码中,我们首先使用 import
语句引入 HelloWorld.vue
组件,并将其赋值给一个变量 HelloWorld
。接着,我们在 App.vue
组件中通过 components
属性将 HelloWorld
注册为子组件,这样就可以在 App.vue
组件的模板中使用 <HelloWorld />
标签来引用 HelloWorld
组件了。
需要注意的是,在 components
属性中注册子组件时,子组件的名称必须与在模板中使用的标签名相同,否则会出现无法渲染组件的错误。此外,还需要将子组件的选项对象(例如 name
和 props
)一并导出,以便在父组件中使用子组件时能够正常工作。
APP.vue
通过路由来调用其他组件
在 Vue.js
中,可以使用 Vue Router
来管理应用程序的路由。在 app.vue
中,可以通过定义路由来调用其他 Vue
组件。
首先,需要在 app.vue
中引入 Vue Router
并定义路由,例如:
在 App.vue
组件中,我们通常会使用 Vue Router
来实现路由功能,以便用户可以在不同的页面之间切换。
<template>
<div>
<router-view></router-view>
</div>
</template>
<script>
import VueRouter from 'vue-router';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';
const router = new VueRouter({
routes: [
{ path: '/component-a', component: ComponentA },
{ path: '/component-b', component: ComponentB },
]
});
export default {
name: 'App',
router
};
</script>
在上述代码中,通过引入 VueRouter
并创建一个新的 VueRouter
实例来定义路由。然后,可以在 routes
中定义路由路径和对应的组件,例如 /component-a
对应 ComponentA
组件,/component-b
对应 ComponentB
组件。
在 app.vue
的模板中,使用 <router-view>
标签来渲染当前路由对应的组件。
这样,当用户访问 /component-a
或 /component-b
路径时,Vue Router 会自动加载对应的组件,并渲染到 <router-view>
标签中。
对应的index.js文件的代码应该如下所示:
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';
import About from '../views/About.vue';
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
}
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
});
export default router;
在这个例子中,我们首先引入了 Vue
和 VueRouter
,然后通过 Vue.use(VueRouter)
来告诉 Vue 使用 Vue Router。
接下来,我们定义了一个 routes
数组,其中包含了两个路由对象。每个路由对象都包含了一个 path
属性表示路由路径,一个 name
属性表示路由名称,和一个 component
属性表示要渲染的组件。
在这个例子中,我们定义了两个组件 Home
和 About
,它们分别对应了两个路由。你可以根据自己的需求定义不同的组件来对应不同的路由。
最后,我们通过 new VueRouter()
创建了一个 Vue Router
实例,并传入了一个包含所有路由信息的 routes
数组。同时,我们也可以在这里配置一些其他的选项,比如 mode
、base
等。
最后,我们通过 export default router
导出了这个 Vue Router 实例,使得其他组件可以使用这个实例来进行路由的跳转和管理。
总结
main.js
import { createApp } from 'vue'//创建一个vue实例
import App from './App.vue'//引入模块
import router from './router'
//通过 data 选项定义数据属性,以便在页面中显示动态数据
createApp(App).use(router).mount('#app')//将应用实例挂载到 #app DOM 元素中,以便渲染应用界面
app.vue
<template>
<div>
<h1>Hello, {{ name }}!</h1>
<router-view />
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
name: 'hhh',
}
}
}
</script>
router index.js
在上面的代码中,我们首先从
vue-router
模块中导入了createRouter
和createWebHistory
方法,并分别用于创建路由对象和路由模式。接着,我们定义了一个路由配置数组
routes
,其中包含了三个路由对象,分别对应了三个不同的路由路径和对应的组件。在这里,我们使用了@
符号来表示应用的根目录,因此@/views
目录对应了src/views
目录。最后,我们通过
createRouter
方法创建了一个路由对象,并将路由配置数组传入其中。同时,我们使用createWebHistory
方法创建了一个history
对象,并将其作为选项传入路由对象中,以便选择使用 HTML5 History API 或者 hash 模式来实现路由跳转。在最后一行代码中,我们将路由对象
router
导出,以便在应用中引用它。这样,我们就可以在应用中使用<router-link>
组件来进行路由跳转了。
import { createRouter, createWebHistory } from 'vue-router'
//
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
import Contact from '@/views/Contact.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
{
path: '/contact',
name: 'Contact',
component: Contact
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
显示一个about组件对应的配置和代码
具体的一个实例
-
在
src/views
目录下创建About.vue
文件,并在其中编写About
组件的模板和样式代码。例如:About
组件<template> <div> <h1>About Page</h1> <p>This is the About page.</p> </div> </template> <style> h1 { font-size: 2rem; } p { font-size: 1.2rem; } </style>
2.在
src/router/index.js
文件中,添加一个路由对象,将/about
路径映射到About
组件。例如:index.js
import { createRouter, createWebHistory } from 'vue-router' import Home from '@/views/Home.vue' import About from '@/views/About.vue' const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: About } ] const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes }) export default router
3.在
src/App.vue
文件中,添加<router-view>
组件,以便显示路由对应的组件。例如app.vue
<template> <div> <h1>My App</h1> <router-view /> </div> </template> <script> export default { name: 'App' } </script>
4.在
src/main.js
文件中,创建Vue
实例,并将其挂载到#app
元素上。例如:mian.js
import { createApp } from 'vue' import App from './App.vue' import router from './router' createApp(App).use(router).mount('#app')
这样,当用户在应用中访问
/about
路径时,将会自动加载About
组件的模板和样式,并显示在<router-view>
组件中。
!解决一个代码报错问题
[vite] Internal server error: Failed to resolve import "./App.vue" from "main.js". Does the file exist?
因为粗心导致项目中加入了2个mian.js
文件,运行代码时一直报错,解决不了,后来一直查看路径问题,得以解决!
选择界面代码
Html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>//用于承载应用程序的内容。这个元素的`id`属性为`app`,用于与JavaScript代码中的应用程序实例进行关联。
<script type="module" src="/src/main.js"></script> /*浏览器会自动下载并执行这个文件,启动应用程序并将其挂载到`<div id="app">`元素上*/
</body>
</html>
这是一个HTML文档的模板,其中包含了一个空的<div>
元素和一个指向应用程序的JavaScript文件的<script>
标签。以下是对各个部分的解释:
<!DOCTYPE html>
:这是HTML5的文档类型声明,告诉浏览器使用HTML5解析文档。<html lang="en">
:这是HTML文档的根元素,其中lang
属性指定了文档的语言为英语。<head>
:这是HTML文档的头部,包含了一些元数据和外部资源,如网页标题、字符集、样式表、脚本等。<meta charset="UTF-8">
:这是一个元数据标签,指定了文档使用的字符编码为UTF-8。<link rel="icon" href="/favicon.ico">
:这是一个元数据标签,指定了网站的图标文件路径。这个文件通常是一个ICO或PNG格式的图像文件,用于在浏览器标签页或地址栏中显示网站的标识。<meta name="viewport" content="width=device-width, initial-scale=1.0">
:这是一个元数据标签,指定了文档的视口(viewport)的初始大小和缩放比例。视口是浏览器中用于渲染网页的区域,可以通过这个标签来控制网页在不同设备上的显示效果。<title>Vite App</title>
:这是网页的标题,显示在浏览器的标签页上。<body>
:这是HTML文档的主体部分,包含了网页的内容和结构。<div id="app"></div>
:这是一个空的<div>
元素,用于承载应用程序的内容。这个元素的id
属性为app
,用于与JavaScript代码中的应用程序实例进行关联。<script type="module" src="/src/main.js"></script>
:这是一个指向应用程序的JavaScript文件的<script>
标签。这个文件包含了应用程序的代码和依赖项,使用了ES模块化的语法。浏览器会自动下载并执行这个文件,启动应用程序并将其挂载到<div id="app">
元素上。
mian.js
import { createApp } from "vue"
import App from "./App.vue"
import router from "./router"
import axios from "axios"
import "./assets/base.css"
const app = createApp(App)
app.config.globalProperties.$http = axios
app.use(router)
app.mount("#app")
这段代码是使用Vue.js 3.x构建应用程序的常见模板。
第一行使用Vue.js的createApp
函数创建了一个应用程序实例,并将其命名为app
。createApp
函数是Vue.js 3.x中用于创建应用程序实例的方法。
第二行将axios
库赋值给了Vue.js的全局属性$http
,这样在应用程序的任何组件中都可以通过this.$http
来使用axios
库。Vue.js的config.globalProperties
属性可以用于向应用程序实例中添加全局属性和方法。
第三行使用Vue.js的use
方法来安装Vue.js的插件(plugin),在这个例子中,我们使用Vue.js的路由插件router
。路由插件提供了在单页应用程序中导航的能力,使得应用程序可以在不刷新页面的情况下切换不同的视图。
最后一行使用Vue.js的mount
方法将应用程序实例挂载到DOM中的一个元素上,这个元素的ID为#app
。这样,Vue.js就可以控制这个元素及其子元素,使得应用程序的视图可以动态地更新和渲染
挂载到DOM的一个元素中具体解释:
在Web开发中,HTML文档的结构可以被视为一棵DOM(Document Object Model)树,它由不同的HTML元素(如<html>
、<head>
、<body>
等)组成,这些元素可以包含子元素和属性。在Vue.js中,应用程序实例需要与DOM中的某个元素进行关联,以便能够动态地更新和渲染视图。
Vue.js提供了mount
方法,用于将应用程序实例挂载到DOM中的一个元素上。这个方法需要传入一个CSS选择器或一个实际的DOM元素作为参数,它会将应用程序实例与该元素进行关联,使得该元素及其子元素成为应用程序的根节点。这个过程被称为挂载(mounting)。
例如,如果我们希望将应用程序实例挂载到一个ID为app
的元素上,可以使用以下代码:
const app = createApp(App)
// ...其他代码...
app.mount('#app')
App.vue
<template>
<router-view></router-view>
</template>
<script>
export default {
data() {
return {
name: "hhh",
}
},
}
</script>
<style lang="scss" scoped></style>
这是一个Vue.js单文件组件的模板,其中包含了模板、脚本和样式三个部分。以下是对各个部分的解释:
<template>
:这是模板部分,包含了视图的HTML结构。在这个例子中,模板中只有一个<router-view>
标签,用于渲染路由组件的内容。<script>
:这是脚本部分,包含了组件的逻辑代码。在这个例子中,脚本定义了一个名为name
的数据属性,值为字符串"hhh"。该属性可以在模板中通过插值表达式或指令引用,或者在脚本中通过this.name
访问。export default
:这是导出语句,将Vue.js组件实例导出为默认模块,供其他模块导入和使用。<style>
:这是样式部分,包含了视图的CSS样式。lang="scss"
表示使用SCSS预处理器来编写样式。scoped
属性表示这个样式仅对当前组件起作用,不会影响其他组件的样式。
需要注意的是,以上三个部分的内容都必须放在同一个文件中,并且必须按照Vue.js的规定格式编写,才能被Vue.js解析和渲染。这是Vue.js单文件组件的一个特点,也是其强大和灵活的基础。
router-index.js文件
import { createRouter, createWebHistory } from "vue-router"
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
component: () => import("../views/Select.vue"),
},
{
path: "/selectheight",
component: () => import("../views/SelectHeight.vue"),
},
],
})
export default router
这是一个使用Vue.js的vue-router库创建路由的代码段。以下是对各个部分的解释:
import { createRouter, createWebHistory } from "vue-router"
:这是ES6模块导入语句,用于导入vue-router库中的createRouter
和createWebHistory
两个函数。const router = createRouter({ ... })
:这是创建Vue.js路由实例的语句,其中createRouter
函数返回一个路由实例对象,包含路由配置和一些方法。这里使用了对象字面量语法,传递了两个参数:history
和routes
。history: createWebHistory(import.meta.env.BASE_URL)
:这里使用createWebHistory
函数创建了一个HTML5的history模式路由,将BASE_URL
作为选项传递给createWebHistory
函数。BASE_URL
是从环境变量中获取的,通常用于指定Vue.js应用的基本URL路径,以便正确处理相对路径和绝对路径之间的转换。routes: [ ... ]
:这是定义Vue.js路由的语句,其中routes
是一个数组,包含了多个路由对象,每个路由对象表示一个页面的路由。这里定义了两个路由对象,分别表示根路径"/“和”/selectheight"的路由。component: () => import("../views/Select.vue")
:这是使用动态导入语法(即函数式导入)导入路由组件的语句,component
属性值是一个函数,用于按需加载路由组件。这里使用了箭头函数,调用了import()
函数动态导入路由组件文件。export default router
:这是导出Vue.js路由实例的语句,可以在其他组件中导入并使用该实例。这里使用了ES6模块默认导出语法,将路由实例对象作为默认导出项
https://element-plus.org/zh-CN/component/descriptions.html#%E5%9E%82%E7%9B%B4%E5%88%97%E8%A1%A8)
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: “/”,
component: () => import(“…/views/Select.vue”),
},
{
path: “/selectheight”,
component: () => import(“…/views/SelectHeight.vue”),
},
],
})
export default router
这是一个使用Vue.js的vue-router库创建路由的代码段。以下是对各个部分的解释:
- `import { createRouter, createWebHistory } from "vue-router"`:这是ES6模块导入语句,用于导入vue-router库中的`createRouter`和`createWebHistory`两个函数。
- `const router = createRouter({ ... })`:这是创建Vue.js路由实例的语句,其中`createRouter`函数返回一个路由实例对象,包含路由配置和一些方法。这里使用了对象字面量语法,传递了两个参数:`history`和`routes`。
- `history: createWebHistory(import.meta.env.BASE_URL)`:这里使用`createWebHistory`函数创建了一个HTML5的history模式路由,将`BASE_URL`作为选项传递给`createWebHistory`函数。`BASE_URL`是从环境变量中获取的,通常用于指定Vue.js应用的基本URL路径,以便正确处理相对路径和绝对路径之间的转换。
- `routes: [ ... ]`:这是定义Vue.js路由的语句,其中`routes`是一个数组,包含了多个路由对象,每个路由对象表示一个页面的路由。这里定义了两个路由对象,分别表示根路径"/"和"/selectheight"的路由。
- `component: () => import("../views/Select.vue")`:这是使用动态导入语法(即函数式导入)导入路由组件的语句,`component`属性值是一个函数,用于按需加载路由组件。这里使用了箭头函数,调用了`import()`函数动态导入路由组件文件。
- `export default router`:这是导出Vue.js路由实例的语句,可以在其他组件中导入并使用该实例。这里使用了ES6模块默认导出语法,将路由实例对象作为默认导出项
https://element-plus.org/zh-CN/component/descriptions.html#%E5%9E%82%E7%9B%B4%E5%88%97%E8%A1%A8)