学生成长画像系统前端的一些感悟和知识积累

1 篇文章 0 订阅

综合实训

本次笔记主要是在做前端项目的时候涉及前端的一些基础知识,主要包括以下内容

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拉取服务器最新代码,以免冲突!

视频资源汇总

  1. https://learngitbranching.js.org/ git语句练习平台 — 适用于全体同学
  2. https://docs.oracle.com/javase/8/docs/api/index.html java开发文档,不建议全文阅读,建议阅读重点类,如ArrayList, HashMap等 — 适用于后端开发同学
  3. https://www.iconfont.cn/home/index 前端资源,如字体、icon等 — 适用于前端开发同学
  4. https://www.imooc.com/learn/945 springboot、mybatis、mysql的使用(只看前3章就可以) — 适用于后端开发同学
  5. https://www.bilibili.com/video/BV1AT4y1w7pH vue基础 — 适用于前端开发同学
  6. https://blog.csdn.net/weixin_45295447/article/details/124825881 接口mock教程 — 适用于前端开发同学
  7. https://blog.csdn.net/weixin_58448088/article/details/123187457 git安装和使用

搜索和高级搜索页面编写进程

select.vue和selectheight.vue

点击搜索逻辑的设计,调试可行**this.isShow 用于控制组件的显示与隐藏**

image-20230517120850646
<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属性。如果请求失败,则在控制台中打印出错误信息

使用同样的方法编写高级搜索的界面,唯一区别是在搜索条件做了相应的改变

image-20230517120928654
        .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>
image-20230517120422740

科研创新的图和上一个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' },
])
image-20230517120343449

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)',
          },
        },
      },
    ],
  })
}
image-20230517121843832

接口封装

一开始我是直接用axios写接口,老师说接口比较繁琐的画,会很麻烦,建议将接口封装

vue的接口封装

自己模仿写的封装接口

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和post传参的区别

  1. 封装接口的时候get传参需要用params,post传参直接写data就好
  2. 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: ''})
  1. assetsUrl 变量:这是一个响应式引用(ref),它的初始值是 '../../../src/assets/'。它表示了一个路径,用于引用组件中的静态资源(例如图片)的根目录。
  2. onMounted 钩子函数:生命周期钩子函数。它在组件挂载到 DOM 后立即执行。在这个函数中,会输出日志信息 "123===>",并打印 props.studentInfo 的值。props 是组件的属性对象,studentInfo 是其中一个属性。
  3. onUpdated 钩子函数:生命周期钩子函数。它在组件的更新周期中被调用。在这个函数中,会更新 detail.circleUrl 的值。detail 是一个使用 reactive 函数创建的响应式对象,它包含一个属性 circleUrl,初始值为空字符串。
  4. 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就会有那个运行的接口了!

前端文件源码的大致分配,项目文件具体介绍

image-20230330115135489 image-20230406173326542

Vscode项目终端根目录键入npm list vue可查看自己是vue2还是vue3,例如,我是vue3项目

image-20230330154622981

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 库变成了 vuepackage 包,需要使用 ES6 的模块化引入方式。
  • render 函数变成了模板 template,可以直接使用 .vue 文件的方式来定义模板。
  • new Vue() 变成了 createApp() 方法。
  • el 属性被移除了,需要使用 mount() 方法来挂载实例。

另外,如果你在 App.vue 中使用了 template 标签来定义模板,也需要将其改为单文件组件的写法,即将 template 标签内容直接写在 .vue 文件的 <template> 标签中

vue项目运行流程

具体可详情查看这篇博客,Vue项目启动代码执行流程分析

这篇主要介绍整个流程是干嘛的,每个命令主要讲了什么内容[Vue运行流程]([(38条消息) Vue运行流程_vue项目运行流程_qq_45436798的博客-CSDN博客](https://blog.csdn.net/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 包含项目的名称版本、项目依赖等相关信息!

image-20230406172005599
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 实例挂载到 idapp 的 DOM 元素上,这样 Vue.js 就能够自动渲染 App.vue 组件中的内容了。在 App.vue 组件中,我们可以使用 templaterender 函数来定义组件的内容。当 Vue.js 实例被挂载到 DOM 上后,Vue.js 会自动解析 App.vue 组件中的模板,并将其渲染到挂载的 DOM 元素上。

App.vue调用单独其他组件的一个过程

App.vueVue 应用的根组件,它是 Vue 组件中最顶层的一个组件,负责组装其他的子组件,提供整个应用的布局和样式。

在一个 Vue 应用中,通常会将 App.vue 组件作为整个应用的入口组件,它会作为整个页面的最外层容器,负责渲染其他组件,并提供应用所需要的共享资源,例如路由、状态管理、全局样式等。

App.vue 组件通常由三部分组成:

  1. 模板(template):负责组装其他子组件,并定义整个应用的布局和结构。
  2. 脚本(script):提供组件的逻辑和行为,例如事件处理、数据处理等。
  3. 样式(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 属性中注册子组件时,子组件的名称必须与在模板中使用的标签名相同,否则会出现无法渲染组件的错误。此外,还需要将子组件的选项对象(例如 nameprops)一并导出,以便在父组件中使用子组件时能够正常工作。

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;

在这个例子中,我们首先引入了 VueVueRouter,然后通过 Vue.use(VueRouter) 来告诉 Vue 使用 Vue Router。

接下来,我们定义了一个 routes 数组,其中包含了两个路由对象。每个路由对象都包含了一个 path 属性表示路由路径,一个 name 属性表示路由名称,和一个 component 属性表示要渲染的组件。

在这个例子中,我们定义了两个组件 HomeAbout,它们分别对应了两个路由。你可以根据自己的需求定义不同的组件来对应不同的路由。

最后,我们通过 new VueRouter() 创建了一个 Vue Router 实例,并传入了一个包含所有路由信息的 routes 数组。同时,我们也可以在这里配置一些其他的选项,比如 modebase 等。

最后,我们通过 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 模块中导入了 createRoutercreateWebHistory 方法,并分别用于创建路由对象和路由模式。

接着,我们定义了一个路由配置数组 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组件对应的配置和代码

具体的一个实例

  1. 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函数创建了一个应用程序实例,并将其命名为appcreateApp函数是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库中的createRoutercreateWebHistory两个函数。
  • const router = createRouter({ ... }):这是创建Vue.js路由实例的语句,其中createRouter函数返回一个路由实例对象,包含路由配置和一些方法。这里使用了对象字面量语法,传递了两个参数:historyroutes
  • 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)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值