Day15 Web前端实战:Vue工程化、ElementPlus


目录
Web开发
图1 Web开发

什么是Vue

图2 Vue构建用户界面、渐进式生态

1. Vue工程化

小白眼中的前端开发

图3 小白眼中的前端开发

工程化

图4 工程化(模块化、组件化、规范化、自动化)

1.1 环境准备

图5 NodeJS
node -v
npm -v

配置npm的全局安装路径、切换为淘宝镜像,加速下载

npm config set prefix "D:\develop\nodejs"
npm config set registry https://registry.npmmirror.com
图7 NodeJS安装验证

1.2 Vue项目简介

Vue项目-创建

Vue项目-安装依赖

 # 项目工作目录 如G:\workspace\duSSM\vue
 npm create vue@3.3.4
 # 输入项目名 vue-project1
 cd vue-project1
 npm install 
 npm run dev
图8 Vue项目-创建验证

Vue项目-项目结构

使用VS Code打开Vue项目。

图9 Vue项目-项目结构


Vue项目-启动

图10 Vue项目-启动
图11 Vue项目初始界面

小结

图12 小结

③ Vue项目执行流程

index.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>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>
src\main.js
import { createApp } from 'vue';
import App from './App.vue'

//import './assets/main.css'

createApp(App).mount('#app')
src\App.vue
<!--定义JS,控制模板部分的数据和行为(JS)-->
<script setup>
  import { ref } from 'vue'
  //声明一个响应式数据message
  const message = ref('Hello Vue3 张婧怡');
</script>

<!--模板部分,控制的是页面的结构(HTML)-->
<template>
  <h1>{{ message }}</h1>
</template>

<!--当前组件的css样式-->
<style scoped>

</style>
图13 验证
图14 Vue项目执行流程
图15 Vue 的单文件组件

.vue是Vue项目中的组件文件扩展名,在Vue项目中也称为单文件组件(SFC,Single-File Components)。Vue 的单文件组件会将一个组件的逻辑 (JS),模板 (HTML) 和样式 (CSS) 封装在同一个文件里(*.vue) 。

④ API风格

图16 API风格
src\views\ApiDemo.vue
<script setup>
//引入ref函数
import { ref,onMounted } from'vue';
//声明响应式数据
const count = ref(0);

//声明函数-在组合式API中没有this
function increment(){
  count.value++;
}

//钩子函数
onMounted(()=> {
console.log('Vue mounted..');
})
</script>
<template>
  <button @click="increment">点击我(张婧怡) 计数:{{ count }}</button>
</template>
<style scoped>
button{
  background-color: #4CAF50;
  color: white;
  padding: 14px 20px;
  margin: 8px 0;
  border: none;
  cursor: pointer;
  width: 50;
}
</style>
src\App.vue
<!--定义JS,控制模板部分的数据和行为(JS)-->
<script setup>
  import ApiDemo from'./views/ApiDemo.vue'
</script>

<!--模板部分,控制的是页面的结构(HTML)-->
<template>
  <ApiDemo></ApiDemo>
</template>

<!--当前组件的css样式-->
<style scoped>

</style>
图17 验证
图18 组合式API

⑤ 案例

在Vue项目中基于组合式API完成用户列表数据渲染

src\views\EmpList.vue
<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';
//声明响应式数据
const name = ref('');
const gender = ref('');
const job = ref('');
const userList = ref([]);

//声明函数 -箭头函数 - await&async
const search = async () => {
  //基于axios发送异步请求,请求服务器端加载数据
  const result=await axios.get(`https://web-server.itheima.net/emps/list?name=${name.value}&gender=${gender.value}&job=${job.value}`);
  userList.value = result.data.data;
}

//钩子函数
onMounted(()=>{
  search();
})
</script>

<template>
  <div id="center">
    姓名: <input type="text" name="name" v-model="name">

    性别:
    <select name="gender" v-model="gender">
      <option value="1"></option>
      <option value="2"></option>
    </select>

    职位:
    <select name="job" v-model="job">
      <option value="1">班主任</option>
      <option value="2">讲师</option>
      <option value="3">其他</option>
    </select>

    <input class="btn" type="button" value="查询(张婧怡)" @click="search">
  </div>

  <table>
    <tr>
      <th>序号</th>
      <th>姓名</th>
      <th>头像</th>
      <th>性别</th>
      <th>职位</th>
      <th>入职时间</th>
      <th>更新时间</th>
    </tr>

    <!-- v-for 用于列表循环渲染元素 -->
    <tr v-for="(user, index) in userList" :key="user.id">
      <td>{{index + 1}}</td>
      <td>{{user.name}}</td>
      <td> <img :src="user.image"> </td>
      <td>
        <span v-if="user.gender == 1"></span>
        <span v-else-if="user.gender == 2"></span>
        <span v-else>其他</span>
      </td>
      <td>
        <span v-if="user.job == 1">班主任</span>
        <span v-else-if="user.job == 2">讲师</span>
        <span v-else-if="user.job == 3">学工主管</span>
        <span v-else-if="user.job == 4">教研主管</span>
        <span v-else-if="user.job == 5">咨询师</span>
        <span v-else>其他</span>
      </td>
      <td>{{user.entrydate}}</td>
      <td>{{user.updatetime}}</td>
    </tr>
  </table>
</template>

<style scoped>
  table,th,td {
    border: 1px solid #000;
    border-collapse: collapse;
    line-height: 50px;
    text-align: center;
  }

  #center,table {
    width: 60%;
    margin: auto;
  }

  #center {
    margin-bottom: 20px;
  }

  img {
    width: 50px;
  }

  input,select {
    width: 17%;
    padding: 10px;
    margin-right: 30px;
    border: 1px solid #ccc;
    border-radius: 4px;
  }

  .btn {
    background-color: #ccc;
  }
</style>
src\App.vue
<!--定义JS,控制模板部分的数据和行为(JS)-->
<script setup>
  import ApiDemo from'./views/ApiDemo.vue'
  import EmpList from'./views/EmpList.vue'
</script>

<!--模板部分,控制的是页面的结构(HTML)-->
<template>
  <ApiDemo></ApiDemo>
  <EmpList></EmpList>
</template>

<!--当前组件的css样式-->
<style scoped>

</style>
图19 验证
小结

在组合式API中有没有this ? 在组合式API中如何更新响应式数据内容 ?

图20 小结

2. ElementPlus

什么是ElementPlus

图21 ElementPlus组件对比
目录

① 快速入门

Element Plus快速入门
//引入ElementPlus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
createApp(App).use(ElementPlus).mount('#app')
 # 项目工作目录 如G:\workspace\duSSM\vue
 npm create vue@3.3.4
 # 输入项目名 vue-project2
 cd vue-project2
 npm install
 npm install element-plus@2.4.4 --save
 npm run dev
图22 创建vue项目vue-project2
index.html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Element Plus快速入门(张婧怡)</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>
src\main.js
import { createApp } from 'vue'
//引入ElementPlus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'

createApp(App).use(ElementPlus).mount('#app')
src\App.vue
<script setup>
  import ElementDemo from './views/ElementDemo.vue'
</script>

<template>
  <h1>Element Demo(张婧怡)</h1>
  <hr />
  <ElementDemo />
</template>

<style scoped>

</style>
src\views\ElementDemo.vue
<script setup>
import {
  Check,
  Delete,
  Edit,
  Message,
  Search,
  Star,
} from '@element-plus/icons-vue'
</script>

<template>
  <div class="button-row">
    <el-button>Default</el-button>
    <el-button type="primary">Primary</el-button>
    <el-button type="success">Success</el-button>
    <el-button type="info">Info</el-button>
    <el-button type="warning">Warning</el-button>
    <el-button type="danger">Danger</el-button>
  </div>

  <div class="button-row">
    <el-button plain>Plain</el-button>
    <el-button type="primary" plain>Primary</el-button>
    <el-button type="success" plain>Success</el-button>
    <el-button type="info" plain>Info</el-button>
    <el-button type="warning" plain>Warning</el-button>
    <el-button type="danger" plain>Danger</el-button>
  </div>
  <div class="button-row">
    <el-button :icon="Search" circle />
    <el-button type="primary" :icon="Edit" circle />
    <el-button type="success" :icon="Check" circle />
    <el-button type="info" :icon="Message" circle />
    <el-button type="warning" :icon="Star" circle />
    <el-button type="danger" :icon="Delete" circle />
  </div>
</template>

<style scoped>
.button-row{
  margin-bottom:10px;
}
</style>
图23 Element Plus快速入门验证

小结

ElementPlus的使用步骤

图24 小结

② 常见组件

表格组件

用于展示多条结构类似的数据, 可对数据进行排序、筛选、对比或其他自定义操作。

src\views\ElementDemo.vue 相应位置添加如下代码
  <div class="button-row">
    <el-table :data="tableData" border style="width: 40%">
      <el-table-column prop="date" label="生日" width="180" align="center" />
      <el-table-column prop="name" label="姓名" width="180" align="center" />
      <el-table-column prop="address" label="住址" header-align="center" />
    </el-table>
  </div>

<script>
const tableData = [
  { date: '2016-05-03', name: '张婧怡1', address: '南内环西街1号' },
  { date: '2016-05-02', name: '张婧怡2', address: '高校新区文华街125号' },
  { date: '2016-05-04', name: '张婧怡3', address: '南内环西街1号' },
  { date: '2016-05-01', name: '张婧怡4', address: '南内环西街1号' }]
</script>
图25 ElementPlus表格验证
小结
图26 小结

分页条组件

//引入中文语言
import zhCn from 'element-plus/es/locale/lang/zh-cn'
createApp(App).use(ElementPlus, { locale: zhCn }).mount('#app')
src\main.js 修改如下
import { createApp } from 'vue';
//引入ElementPlus
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import zhCn from 'element-plus/es/locale/lang/zh-cn';
import App from './App.vue';

createApp(App).use(ElementPlus, { locale: zhCn }).mount('#app')
src\views\ElementDemo.vue 相应位置添加如下代码
<script setup>
mport { ref } from 'vue';

  const currentPage=ref(1);//当前页码
  const pagesize=ref(10);//每页展示记录数
  const total=ref(400);//总记录数
  const background=ref(true);//是否有背景色

  const handlesizeChange = (val)=> {
    console.log(`每页展示:${val}`);
  }

  const handleCurrentchange= (val)=> {
    console.log(`当前页码是:${val}`);
  }
</script>


  <div class="button-row">
    <el-pagination
      :current-page="currentPage"
      :page-sizes="[10, 20, 30, 45]"
      :page-size="pagesize"
      :Background="background"
      class="pagination"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handlesizeChange"
      @current-change="handleCurrentchange"
    />
  </div>
图27 ElementPlus分页条组件验证
图28 分页条组件小结

对话框组件

在保留当前页面状态的情况下,告知用户并承载相关操作。

src\views\ElementDemo.vue 相应位置添加如下代码
<script>
  const dialogTableVisible = ref(false);
</script>

<div class="button-row">
    <el-button class="!ml-0" plain @click="dialogTableVisible = true">打开Dialog对话框</el-button>
    <el-dialog v-model="dialogTableVisible" title="收货地址" width="500">
      <el-table :data="tableData">
        <el-table-column property="date" label="日期" width="120" />
        <el-table-column property="name" label="姓名" width="100" />
        <el-table-column property="address" label="收货地址" />
      </el-table>
    </el-dialog>
  </div>
图29 ElementPlus对话框组件验证
图30 对话框组件小结

表单组件

表单包含 输入框, 单选框, 下拉选择, 多选框 等用户输入的组件。 使用表单,可以收集、验证和提交数据。

src\views\ElementDemo.vue 相应位置添加如下代码
<script>
  //表单
  const user = ref({
    username: '',
    gender: '',
    hiredate: '',
  })

  const onSubmit = () => {
    console.log(user.value)
  }
</script>

  <div class="button-row">
    <el-form :inline="true" :model="user" class="demo-form-inline">
      <el-form-item label="用户名">
        <el-input v-model="user.username" placeholder="请输入用户名" clearable />
      </el-form-item>
      <el-form-item label="性别">
        <el-select
          v-model="user.gender"
          placeholder="请选择性别">
          <el-option label="" value="1" />
          <el-option label="" value="0" />
        </el-select>
      </el-form-item>
      <el-form-item label="入职日期">
        <el-date-picker
          v-model="user.hiredate"
          type="date"
          placeholder="请选择"
          value-format="YYYY-MM-DD"
          clearable
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">提交</el-button>
      </el-form-item>
    </el-form>
  </div>
图31 ElementPlus表单验证
图32 表单组件小结

③ 案例

制作如下页面,并异步获取数据完成页面展示

图33 案例需求
src\App.vue 修改如下
<script setup>
  // import ElementDemo from './views/ElementDemo.vue'
  import EmpList from './views/EmpList.vue'
</script>

<template>
  <!-- <h1>Element Demo(张婧怡)</h1> -->
  <h1 style="text-align: center; width: 70%;margin: 0 auto;">员工列表(张婧怡)</h1>
  <hr style="text-align: center; width: 70%;"/>
  <EmpList />
</template>

<style scoped>

</style>
src\views\EmpList.vue
<script setup>
  import { ref, onMounted } from 'vue';
  import axios from 'axios'
  //表单
  const emp = ref({name: '', gender: '', job: '' })
  const empList = ref([]);
  const sertch = async () => {
    const res = await axios.get('https://web-server.itheima.net/emps/list', { params: emp.value})
    empList.value = res.data.data
  }
  const clear = () => {
      emp.value = {name: '', gender: '', job: '' }
      sertch()
  }
  onMounted(() => {
    sertch()
  })

  // 时间格式化
  const formatDateTime = (row, column) => {
    const date = row[column.property];
    if (!date) return '';
    // 将T替换为空格
    return date.replace('T', ' ');
  }
</script>

<template>

  <div id="container">
    <el-form :inline="true" :model="emp" class="demo-form-inline">
      <el-form-item label="姓名">
        <el-input v-model="emp.name" placeholder="请输入姓名" clearable />
      </el-form-item>
      <el-form-item label="性别">
        <el-select
          v-model="emp.gender"
          placeholder="请选择性别">
          <el-option label="" value="1" />
          <el-option label="" value="2" />
        </el-select>
      </el-form-item>

      <el-form-item label="职位">
        <el-select
          v-model="emp.job"
          placeholder="请选择">
          <el-option label="班主任" value="1" />
          <el-option label="讲师" value="2" />
          <el-option label="学工主管" value="3" />
          <el-option label="教研主管" value="4" />
          <el-option label="咨询师" value="5" />
        </el-select>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="sertch">查询</el-button>
        <el-button type="info" @click="clear">清空</el-button>
      </el-form-item>
    </el-form>
    <el-table :data="empList" border style="width: 100%">
      <el-table-column prop="id" label="ID" width="100" align="center" />
      <el-table-column prop="name" label="姓名" width="120" align="center" />
      <el-table-column prop="address" label="头像" align="center" width="80">
        <template #default="scope">
          <el-avatar :src="scope.row.image" size="medium" />  
        </template>
      </el-table-column>
      <el-table-column prop="gender" label="性别" width="80" align="center" >
        <template #default="scope">
          {{scope.row.gender == 1 ? '男' : '女'}}
        </template>
      </el-table-column>
      <el-table-column prop="job" label="职位" width="120" align="center" >
        <template #default="scope">
          <span v-if="scope.row.job == 1">班主任</span>
          <span v-else-if="scope.row.job == 2">讲师</span>
          <span v-else-if="scope.row.job == 3">学工主管</span>
          <span v-else-if="scope.row.job == 4">教研主管</span>
          <span v-else-if="scope.row.job == 5">咨询师</span>
          <span v-else>其他</span>
        </template>
      </el-table-column>
      <el-table-column prop="entrydate" label="入职日期" align="center" width="180" />
      <el-table-column prop="updatetime" label="更新时间" align="center" :formatter="formatDateTime"  />
    </el-table>
  </div>
</template>

<style scoped>
#container{
  width: 70%;
  margin: 0 auto;
}
</style>
图34 案例验证

返回