7天毕设速成2: elementui搭建

 

 

一.项目创建配置

1.1.项目创建

新建一个空文件夹,在地址栏输入cmd指令

7d16a283a8584bf6a08f9ddabb2ef936.png

在cmd里执行如下命令

1.1.1.项目初始化

npm init -y                                进行初始化

e89585662c5f4c93a54e6af82b9dbec2.png

a3a4bb27913f4389925120d044d915db.png

1.1.2.创建项目脚手架

 npm i -D @vue/cli                    创建脚手架


npx vue -V                               查看脚手架版本指令

d49f82c86180439e94d9cbfee9f5ccba.png

1.1.3.通过脚手架构建项目

npx vue create myvuedemo      通过脚手架构建

1d0a1da06f1b4a40adbb79f7fc444c25.png

aea67b1f94234efb9f74900f8eddf9ad.png

进入项目目录,启动项目

2c2f9fbace7c4500b51cf48e068f55e8.png

ab4024d9596645d4a00e5f4264fb3ccc.png

浏览器输入上面地址,展示页面如下,代表启动成功

b0defe1047414087a29a9c214c027349.png

 

1.2.项目配置

vue前端开发工具一般用 vscode和hbuild,这里我用vscode演示

打开vue.config.js,

f78dc906883d48868ec600a744c9ceda.png

做以下配置

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false ,
  devServer:{
    open:true,//自动打开
    host:'localhost',
    proxy:{ // 配置代理
      '/api':{
        target:'http://localhost:8080',//前后端交互时用
        changeOrigin:true, //允许跨域
        pathRewrite:{
          '^/api':''
        }
      }
    }
  }
})

309db4c871d24c60b3709d95fc371777.png

二.集成elementui框架

2.1.整合elementui

进入myvuedemo文件夹,进入cmd,执行  npm i element-ui -S

3fd7e33de0a14af38218485dd3172e1c.png

打开package.json,可以看到多出很多  elementUI 的东西

1533209003294ae08f7942ee117cf8b3.png

2.2.elementui引用

进入src->main.js里面

import ElementUI from 'element-ui'            //引入ElementUI
import 'element-ui/lib/theme-chalk/index.css' //导入样式
Vue.use(ElementUI)                            //使用

修改原始HelloWorld.vue 改为Home.vue,打开Home.vue,修改内容为elementui的一些按钮

<div class="hello">
    <h1>hello</h1>
    <el-button>hello</el-button>
    <el-button type="primary">hello</el-button>
    <el-button type="info">hello</el-button>
    <el-button type="danger">hello</el-button>
    <el-button type="success">hello</el-button>
</div>

ee64c77d01944372b7dd9c75443e6f88.png

修改app.vue

<template>
  <div id="app">
    <Home/>
  </div>
</template>

<script>
import Home from './components/Home.vue'

export default {
  name: 'App',
  components: {
    Home
  }
}
</script>

81f163db83a6495da94eeeb3968939ed.png

最终效果

45b76b50730947bc836c3add77b2d8f0.png

 

至此,elementui框架集成完毕

三.项目安装配置

3.1.axios安装

进入项目cmd,运行   npm i axios -S

3ee97cd9f7fa4a4684cda63f7da788e1.png

打开main.js,配置 axios 全局引用

import axios from 'axios'                     //引入axios
Vue.prototype.axios = axios                   // 挂载到原型上,可以全局使用

05fb3f4232e84dfd8f1d570906fe51f6.png

3.2.路由安装

进入项目cmd,运行 npm i vue-router@3.5.3 -S   

----- 因为用的是Vue2版本,所以定义一下router的版本

d2b495e1ddd843fca8cfcafda7142124.png

安装完进行配置,在src目录下新建文件夹  router,在该文件夹下创建 index.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from '../components/Home.vue'
Vue.use(Router)
export default new Router({
    routes:[
        {
            path:'/',
            component:Home
        }
    ],
    mode:'history'
})

0058b6a74b6a43779bf91e302b640575.png

使用,在main.js里面导入并在渲染之前挂载一下

import Vue from 'vue'
import App from './App.vue'
import router from './router'

import ElementUI from 'element-ui'            //引入ElementUI
import 'element-ui/lib/theme-chalk/index.css' //导入样式

import axios from 'axios'                     //引入axios
Vue.prototype.axios = axios                   // 挂载到原型上,可以全局使用

Vue.use(ElementUI)                            //使用

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

a4c847fd61744003ac6bf1837d6fa068.png

在app.vue里面加入路由出口, <router-view></router-view>

28354f165d254da4a25601df3eaa3eee.png

最终效果

d394e5ea517b43aeb464764ecb09baaf.png

3.3.路由升级-》路由懒加载

不需要 import Home...,只需要在 componet 后面加 import

import Vue from 'vue'
import Router from 'vue-router'
// import Home from '../components/Home.vue'
Vue.use(Router)
export default new Router({
    routes:[
        {
            path:'/home',
            // component:Home
            component:()=> import('@/components/Home')
        }
    ],
    mode:'history'
})

8899d30bf6104c978bcff895e607415b.png

3.4.路由升级-》异步组件

import Vue from 'vue'
import Router from 'vue-router'
// import Home from '../components/Home.vue'
Vue.use(Router)
export default new Router({
    routes:[
        {
            path:'/home',
            // component:Home
            // component:()=> import('@/components/Home')    //路由懒加载
            component:resolve => require(['@/components/Home'],resolve) // 异步组件
        }
    ],
    mode:'history'
})

81204b73c4874009be4e7924e83d0bd1.png

四.项目实战

4.1.通用登录页面实现

component文件夹创建Login.vue

<template>
    <div class="login">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>XXXXXX后台管理系统</span>
      </div>
      <el-form label-width="80px" :model="form" ref="form">
        <el-form-item label="用户名" prop="username" 
        :rules="[
        {required:true,message:'请输入用户名', trigger:'blur'},
        {min:4,max:10,message:'长度在4-10位字符之间', trigger:'blur'}
        ]">
          <el-input v-model="form.username"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password"
        :rules="[
        {required:true,message:'请输入密码', trigger:'blur'},
        {min:6,max:12,message:'长度在6-12位字符', trigger:'blur'}
      ]">
          <el-input type="password" v-model="form.password"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="login('form')">登录</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    </div>
  </template>
  
  <script>
  export default {
    name: 'login',
    data(){
      return {
        form:{
          username:'',
          password:''
        }
      }
    },
    methods:{
      login(form){
          this.$refs[form].validate((valid)=>{
            if(valid){
              console.log(this.form)
            }else{
              console.error(this.form)
            }
          })
      }
    }
  }
  </script>
  
  <!-- Add "scoped" attribute to limit CSS to this component only -->
  <style scoped>
  .login{
    width: 100%;
    height: 100%;
    position: absolute;
    background: #409EFF;
  }
  .box-card{
    width: 450px;
    margin:200px auto;
  }
  </style>

 

修改router文件夹下的index.js

import Vue from 'vue'
import Router from 'vue-router'
// import Home from '../components/Home.vue'
Vue.use(Router)
export default new Router({
    routes:[
        {
            path:'/',
            redirect:'/login',
            hidden:true,
            component:()=> import('@/components/Login') //路由懒加载
        },
        {
            path:'/login',
            name:'/Login',
            hidden:true,
            component:()=> import('@/components/Login') //路由懒加载
        },
        {
            path:'/home',
            // component:Home
            // component:()=> import('@/components/Home')    //路由懒加载
            component:resolve => require(['@/components/Home'],resolve) // 异步组件
        }
    ],
    mode:'history'
})


4.2.   封装2个工具类

在src目录下新建文件夹 utils,新建2个工具类  setToken.js 

// 设置
export function setToken(tokenKey,token){
    return localStorage.setItem(tokenKey,token)
}
// 获取
export function getToken(tokenKey){
    return localStorage.getItem(tokenKey)
}
// 删除
export function removeToken(tokenKey){
    return localStorage.removeItem(tokenKey)
}

和  validate.js

// 用户名匹配
export function nameRule(rule,value,callback){
    // 请输入4-10位的昵称
    let reg = /(^[a-zA-Z0-9]{4,10}$)/;
    if(value === ''){
        callback(new Error('请输入用户名'))
    }else if(!reg.test(value)){ // 校验没有通过
        callback(new Error('请输入4-10位用户名'))
    }else{
        callback()
    }
}
// 用户密码匹配
export function passRule(rule,value,callback){
  // 请输入6-12位的密码,需要包含大小写字母和数字以及特殊符号
  let pass = /^\S*(?=\S{6,12})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/;
  if(value === ''){
      callback(new Error('请输入密码'))
  }else if(!pass.test(value)){ // 校验没有通过
      callback(new Error('6-12位密码需要包含大小写字母和数字及符号'))
  }else{
      callback()
  }
}

在login.vue中使用

918f6f2afe3d46f2bbf709501946d103.png

4.3.封装axios

在src目录下新建service.js

import axios from 'axios'
import {getToken} from '@/utils/setToken.js'
import { Message } from 'element-ui'
const service = axios.create({
    baseURL:'/api', //baseURL会自动加在请求地址上
    timeout:5000
})
// 添加请求拦截器
service.interceptors.request.use((config)=>{
    // 在请求之前做些什么(获取并设置token)
    config.headers['token'] = getToken('token')
    return config
},(error)=>{
    return Promise.reject(error)
})
 
// 添加响应拦截器
service.interceptors.response.use((response)=>{
    // 在响应数据做些什么(获取并设置token)
    let {code, msg} = response.data
    if(code !== 200){
        Message({message: msg || 'error',type:'warning'})
    }
     return response
},(error)=>{
    return Promise.reject(error)
})
export default service

更改main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'

import ElementUI from 'element-ui'            //引入ElementUI
import 'element-ui/lib/theme-chalk/index.css' //导入样式

 //引入axios
//import axios from 'axios' 
import service from './service'
 // 挂载到原型上,可以全局使用                   
// Vue.prototype.axios = axios    
Vue.prototype.service = service     

Vue.use(ElementUI)                            //使用

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

5d69325ec2a54d71b005dbb943fa0610.png

4.4.api请求封装

在src目录下新建api文件夹,创建api.js

// 项目中我们大多数时候都会把对应的接口请求都封装成api来调用
import service from '../service.js'
 
// 登录接口封装   后面再调试
export function login(data){
    return service({
        method: 'post',
        url:'/login',
        data
    })
}

15150a0cc78c4671a45a1563d0ec3704.png

更改login.vue,引用封装

<template>
    <div class="login">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>XXXXXX后台管理系统</span>
      </div>
      <el-form label-width="80px" :model="form" ref="form">
        <el-form-item label="用户名" prop="username" 
        :rules="[
        {required:true,message:'请输入用户名', trigger:'blur'},
        {min:4,max:10,message:'长度在4-10位字符之间', trigger:'blur'}
        ]">
          <el-input v-model="form.username"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password"
        :rules="[
        {required:true,message:'请输入密码', trigger:'blur'},
        {min:6,max:12,message:'长度在6-12位字符', trigger:'blur'}
      ]">
          <el-input type="password" v-model="form.password"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="login('form')">登录</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    </div>
  </template>
  
  <script>
  import {nameRule,passRule } from '@/utils/validate.js'
  import {setToken } from '@/utils/setToken.js'

  import { login } from '@/api/api.js'
  export default {
    name: 'HelloWorld',
    data(){
      return {
        form:{
          username:'',
          password:''
        },
        rules:{
            username:[{validator:nameRule,trigger: 'blur'}],
            password:[{validator:passRule,trigger: 'blur'}]
        }
      }
    },
    methods:{
      login(form){
        setToken('username',"test")
                      setToken('token',"-----")
                      this.$message({message:"res.data.msg", type:'success'})
                      this.$router.push('/home') 
          // this.$refs[form].validate((valid)=>{
          //   if(valid){
          //       console.log(this.form)
          //       let LoginParam = this.form  
          //       login(LoginParam).then(res=>{
          //           if(res.data.code === 200){
          //             setToken('username',res.data.username)
          //             setToken('token',res.data.token)
          //             this.$message({message:res.data.msg, type:'success'})
          //             this.$router.push('/home')
          //         }  
          //       })   
          //   }else{
          //     console.error(this.form)
          //   }
          // })
      }
    }
}
// import { setToken } from '@/utils/setToken'

//   export default {
//     name: 'login',
//     data(){
//       return {
//         form:{
//           username:'',
//           password:''
//         }
//       }
//     },
//     methods:{
//       login(form){
//           this.$refs[form].validate((valid)=>{
//             if(valid){
//               console.log(this.form)
//               setToken('username',this.form.username);
//               this.$router.push('/home')
//             }else{
//               console.error(this.form)
//             }
//           })
//       }
//     }
//   }
  </script>
  
  <!-- Add "scoped" attribute to limit CSS to this component only -->
  <style scoped>
  .login{
    width: 100%;
    height: 100%;
    position: absolute;
    background: #409EFF;
  }
  .box-card{
    width: 450px;
    margin:200px auto;
  }
  </style>

33092d2701774a79ad125970ca4aeea7.png

4.5.创建404页面

在src->components文件夹下新建NotFound.vue

<template>
    <div class="notfound">
        <div class="wrapper">
            <div class="big">页面不见了</div>
            <div>去首页瞧瞧,点击<router-link to="/">这里</router-link>进入首页</div>
        </div>
    </div>
</template>
<script>
export default {
    data(){
        return {};
    }
}
</script>
<style>
.notfpund{
    height: 100%;
    /* background-image: url('../assets/404.jpg'); */
    background-position: right top, center center;
    background-repeat:  no-repeat repeat;
}
.notfound .wrapper .big{
    font-size: 74px;
    font-weight: 700;
    line-height: 68px;
    margin-bottom: 48px;
}
</style>

app.vue中设置样式

<style>
html,body{
  width: 100%;
  height: 100%;
}
#app {
  width: 100%;
  height: 100%;
  font-family:Avenir,Helvetica, Arial, sans-serif;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-align:center;
  color:#2c3e50;
}
</style>

566d3d66a15a48b98c55220c2b891459.png

router文件夹下->index.js下配置404页面路由

  {
            path:'*',
            name:'NotFound',
            hidden:true,
            component:()=> import('@/components/NotFound') //路由懒加载
        },

9672566a016449ccb65bdf3bdec06cf8.png

最终效果如下

435269cf3e7c457ab92de934e61d2af3.png

五。后台页面

5.1.后台布局页面

后台布局一般分头部,左边项目列表,尾部和项目内容,主页面包屑,

在src->components文件夹下创建common文件夹。然后新建

Header.vue,

<template>
    <div class="header">
        <el-header>
            <div class="title">管理系统</div>
            <div>{{name}}</div>
        </el-header>
    </div>
</template>
<script>
import { getToken } from '@/utils/setToken';
export default{
    name:"Header_",
    data(){
        return{
            name:''
        }
    },
    created(){
       this.name = getToken('username')
    }
}
</script>
<style scoped>
.el-header{
    background: #2578b5;
    color:#fff;
    line-height: 60px;
    display: flex;
    justify-content: space-between;
}
.title{
    width: 200px;
    font-size: 24px;
}
</style>

Menu.vue,

<template>
    <div class="menu">
        <el-aside width="200px">
            <el-menu
            router
            default-active="2"
            class="el-menu-vertical-demo"
            background-color="#2578b5"
            text-color="#fff"
            active-text-color="#ffd04b">
 
            <!-- 在这里遍历,进行绑定 -->
            <template v-for="(item,index) in menus">
                <el-submenu :index="index+''" :key="index" v-if="!item.hidden">
                    <template slot="title">
                      <i class="el-icon-location"></i>
                      <span>{{item.name}}</span>
                    </template>
                    <el-menu-item-group v-for="(child,index) in item.children" :key="index">
                      <el-menu-item :index="child.path">{{child.name}}</el-menu-item>
                    </el-menu-item-group>
                    </el-submenu>
            </template>
          </el-menu>
        </el-aside>
    </div>
</template>
<script>
export default{
    name:"menu_",
    data(){
        return{
            menus:[]
        }
    },
    created(){
        console.log(this.$router.options.routes)
        this.menus = [...this.$router.options.routes]
    }
}
</script>
<style scoped>
.el-aside{
    height: 100%;
}
.el-menu{
    height: 100%;
}
.el-submenu-item{
    min-width: 0;
}
</style>

Footer.vue,

<template>
    <div class="footer">
       <el-card>
        @瑞鹏软件工作室
       </el-card>
    </div>
</template>
<script>
export default{
    name:"footer_",
    data(){
        return{}
    }
}
</script>

Breadcrumb.vue

<template>
    <div>
        <el-card>
            <el-breadcrumb separator-class="el-icon-arrow-right">
                <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
                <el-breadcrumb-item
                v-for="(item,index) in $route.matched"
                :key="index"
                >{{item.name}}</el-breadcrumb-item>
              </el-breadcrumb>
        </el-card>
    </div>
</template>
<script>
export default{
    name:"Breadcrumb_",
    data(){
        return{}
    }
}
</script>
<style scoped>
</style>

在Home.vue中导入三个组件

<template>
  <div class="home">
    <!-- 头部 -->
    <Header>Header</Header> 
    <el-container class="content">
      <!-- 左侧菜单栏 -->
        <Menu/>
        <!-- 内容 -->
      <el-container>
        <el-main>Main</el-main>
        <!-- 底部 -->
        <el-footer><Footer/></el-footer>
      </el-container>
    </el-container>
  </div>
</template>
 
<script>
import Header from './common/Header.vue'
import Footer from './common/Footer.vue'
import Menu from './common/Menu.vue'
export default {
  name: 'HelloWorld',
  components:{ //注册
    Header,
    Footer,
    Menu
  },
  data(){
    return {}
  }
}
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  .home{
    width:100%;
    height:100%;
  }
  .content{
    position: absolute;
    width: 100%;
    top:60px;
    bottom: 0;
  }
</style>

最终效果

daa0548624b341af986f03e662b10126.png

5.2. 用户列表静态开发

在components文件夹下创建base文件夹。

新建sysuser.vue

<template>
  <el-table
    :data="tableData"
    style="width: 100%">
    <el-table-column
      label="日期"
      width="180">
      <template slot-scope="scope">
        <i class="el-icon-time"></i>
        <span style="margin-left: 10px">{{ scope.row.date }}</span>
      </template>
    </el-table-column>
    <el-table-column
      label="姓名"
      width="180">
      <template slot-scope="scope">
        <el-popover trigger="hover" placement="top">
          <p>姓名: {{ scope.row.name }}</p>
          <p>住址: {{ scope.row.address }}</p>
          <div slot="reference" class="name-wrapper">
            <el-tag size="medium">{{ scope.row.name }}</el-tag>
          </div>
        </el-popover>
      </template>
    </el-table-column>
    <el-table-column label="操作">
      <template slot-scope="scope">
        <el-button
          size="mini"
          @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
        <el-button
          size="mini"
          type="danger"
          @click="handleDelete(scope.$index, scope.row)">删除</el-button>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
  export default {
    data() {
      return {
        tableData: [{
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        }, {
          date: '2016-05-04',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1517 弄'
        }, {
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1519 弄'
        }, {
          date: '2016-05-03',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1516 弄'
        }]
      }
    },
    methods: {
      handleEdit(index, row) {
        console.log(index, row);
      },
      handleDelete(index, row) {
        console.log(index, row);
      }
    }
  }
</script>

修改路由,进入router->index.js

import Vue from 'vue'
import Router from 'vue-router'
// import Home from '../components/Home.vue'
Vue.use(Router)
export default new Router({
    routes:[
        {
            path:'/',
            redirect:'/login',
            hidden:true,
            component:()=> import('@/components/Login') //路由懒加载
        },
        {
            path:'/login',
            name:'/Login',
            hidden:true,
            component:()=> import('@/components/Login') //路由懒加载
        },
        {
            path:'*',
            name:'NotFound',
            hidden:true,
            component:()=> import('@/components/NotFound') //路由懒加载
        },
        {
            path:'/home',
            name:'基本信息管理',
            redirect:'/home/sysuser',  //默认重定向
            component:()=> import('@/components/Home'),
            children:[
                {
                    path:'/home/sysuser',  
                    name:'用户列表',
                    component:()=> import('@/components/base/sysuser'),//这里对应文件的名字
                }
            ]
        },
 
        // {
        //     path:'/home',
            // component:Home
            // component:()=> import('@/components/Home')    //路由懒加载
        //     component:resolve => require(['@/components/Home'],resolve) // 异步组件
        // }
    ],
    mode:'history'
})


设置路由出口,让Main区域跟着路由变化而显示不同的内容。在Home.vue中修改,把原始的Main改为router-view

<template>
  <div class="home">
    <!-- 头部 -->
    <Header>Header</Header> 
    <el-container class="content">
      <!-- 左侧菜单栏 -->
        <Menu />
        <!-- 内容 -->
      <el-container>
        <el-main>
          <!-- 面包屑 -->
          <Bread />
          <div class="cont">
            <router-view></router-view>
          </div>     
        </el-main>
        <!-- 底部 -->
        <el-footer><Footer /></el-footer>
      </el-container>
    </el-container>
  </div>
</template>
 
<script>
import Bread from './common/Breadcrumb'
import Header from './common/Header.vue'
import Footer from './common/Footer.vue'
import Menu from './common/Menu.vue'
export default {
  name: 'HelloWorld',
  components:{ //注册
    Header,
    Footer,
    Menu,
    Bread
  },
  data(){
    return {}
  }
}
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  .home{
    width:100%;
    height:100%;
  }
  .content{
    position: absolute;
    width: 100%;
    top:60px;
    bottom: 0;
  }
</style>

最终效果

7c4b50b7fa614500b826788ac8a919ee.png

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软件编程工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值