Attachment: https://gitee.com/zhoulililia/vue_shop
1. Background home page basic layout opens Home.vue component, layout:
<el-container class="home-container"> <!-- Head area --> <el-header>Header<el-button type="info" @click="logout"> Sign out </el-button></el-header> <!-- Page Body Area --> <el-container> <!-- sidebar --> <el-aside width="200px">Aside</el-aside> <!-- Principal structure --> <el-main>Main</el-main> </el-container> </el-container>
By default, a class name with the same name as an element-ui component can help us quickly style the corresponding component, such as:
.home-container { height: 100%; } .el-header{ background-color:#373D41; } .el-aside{ background-color:#333744; } .el-main{ background-color:#eaedf1; }
2. Top layout, Sidebar layout
Element-ui, notice to element. Some of the primary keys introduced on demand in JS
<template> <el-container class="home-container"> <!-- Head area --> <el-header> <div> <!-- logo --> <img src="../assets/logo.png" alt=""> <!-- Top Title --> <span>E-commerce Background Management System</span> </div> <el-button type="info" @click="logout"> Sign out </el-button> </el-header> <!-- Page Body Area --> <el-container> <!-- sidebar --> <el-aside width="200px"> <!-- Sidebar Menu --> <el-menu background-color="#333744" text-color="#fff" active-text-color="#ffd04b"> <!-- Level 1 Menu --> <el-submenu index="1"> <!-- Level 1 Menu Template --> <template slot="title"> <!-- Icon --> <i class="el-icon-location"></i> <!-- text --> <span>Navigation One</span> </template> <!-- Secondary Submenu --> <el-menu-item index="1-4-1"> <!-- Secondary Menu Template --> <template slot="title"> <!-- Icon --> <i class="el-icon-location"></i> <!-- text --> <span>Submenu One</span> </template> </el-menu-item> </el-submenu> </el-menu> </el-aside> <!-- Principal structure --> <el-main>Main</el-main> </el-container> </el-container> </template>
3.axios request interceptor
Background requires token privilege validation in addition to the login interface. We can add token by adding axios request interceptor to ensure we have access to data in main. Add code to JS to add the following code before mounting axios to the vue prototype
//The request calls this callback function in use to add the request header information before reaching the server axios.interceptors.request.use(config=>{ //For the request header object, add the Autohorization field for token validation config.headers.Authorization = window.sessionStorage.getItem("token") return config })
4. Request Sidebar Data
<script> export default { data() { return { // Left menu data menuList: null } }, created() { // Request left menu data during the create phase this.getMenuList() }, methods: { logout() { window.sessionStorage.clear() this.$router.push('/login') }, async getMenuList() { // Send a request for left menu data const { data: res } = await this.$http.get('menus') if (res.meta.status !== 200) return this.$message.error(res.meta.msg) this.menuList = res.data console.log(res) } } } </script>
Render left menu with v-for double loop
<el-menu background-color="#333744" text-color="#fff" active-text-color="#ffd04b"> <!-- Level 1 Menu --> <el-submenu :index="item.id+''" v-for="item in menuList" :key="item.id"> <!-- Level 1 Menu Template --> <template slot="title"> <!-- Icon --> <i class="el-icon-location"></i> <!-- text --> <span>{{item.authName}}</span> </template> <!-- Secondary Submenu --> <el-menu-item :index="subItem.id+''" v-for="subItem in item.children" :key="subItem.id"> <!-- Secondary Menu Template --> <template slot="title"> <!-- Icon --> <i class="el-icon-location"></i> <!-- text --> <span>{{subItem.authName}}</span> </template> </el-menu-item> </el-submenu> </el-menu>
5. Set Activation Submenu Style
By changing the active-text-color property of el-menu, you can set the text color of the active item clicked on the sidebar menu. By changing the class name of the i tag in the menu item template, you can set the icon of the left menu bar. We need to add an iconsObj to the data in the project using a third-party font icon:
iconsObj:{ //An id corresponds to an icon '125':'iconfont icon-user', '103':'iconfont icon-tijikongjian', '101':'iconfont icon-shangpin', '102':'iconfont icon-danju', '145':'iconfont icon-baobiao' },
Then bind the icon class name to the data in iconsObj:
To keep the left menu open only one at a time, displaying its sub-menus, we can add a property unique-opened to the el-menu or set it with data binding (true is considered a bool value, not a string at this time):unique-opened="true"
6. Make Side Menu Bar Scalable Add a div above the menu bar
<!-- sidebar,Width is set by folding or not --> <el-aside :width="isCollapse ? '64px':'200px'"> <!-- Scalable Sidebar Button --> <div class="toggle-button" @click="toggleCollapse">|||</div> <!-- Sidebar menu,:collapse="isCollapse"(Set fold menu to bound isCollapse Value),:collapse-transition="false"(Turn off the default fold animation) --> <el-menu :collapse="isCollapse" :collapse-transition="false" ......
Then add styles to the div and events to the div:
<div class="toggle-button" @click="this.isCollapse ? '64px':'200px'">|||</div>
7. Add subrouting to background home page
New subrouting component Welcome.vue
<template> <div> <h3>Welcome</h3> </div> </template>
In router. Import subrouting components into JS and set routing rules and default redirection of subrouting to open Home.vue, adds a routing placeholder to the main's body structure
import Welcome from '../components/Welcome.vue' const router = new VueRouter({ routes: [{ path: '/', redirect: '/login' }, { path: '/login', component: Login }, { path: '/home', component: Home, redirect: '/welcome', children: [ { path: '/welcome', component: Welcome }, //Here ] }] })
After making the Welcome subrouting, we need to transform all the sidebar secondary menus into subrouting links. We just need to set the router property of el-menu to true. When we click on the secondary menu, we will make the route jump according to the index property of the menu, for example: /110, it is not appropriate to use the index id as the route of the jump. We can rebind index to index='/'+subItem.path'
<!-- Level 2 Menu --> <el-menu-item :index="'/'+subItem.path" v-for="subItem in item.children" :key="subItem.id" @click="saveNavState('/'+subItem.path)">
8. Complete the user list body area
Create a new user list component user/Users.vue in router. Import subrouting component Users in js. Vue and set routing rules
Because user is a sub-component of re/home to be placed in child ren and welcome
const router = new VueRouter({ routes: [{ path: '/', redirect: '/login' }, { path: '/login', component: Login }, { path: '/home', component: Home, redirect: '/welcome', children: [ { path: '/welcome', component: Welcome }, { path: '/users', component: Users }, ] }] })
When clicking on Level 2 menu, the clicked Level 2 submenu is not highlighted. We need to highlight the function being used
We can set the index of the current activation menu by setting the default-active property of el-menu
But the default-active attribute cannot be written to death, fixed to a menu value
So we can first add a click event to all the secondary menus and use the path value as a parameter of the method
@click="saveNavState('/'+subItem.path)"
Save path to sessionStorage in saveNavState method
//Save Link Activation State saveNavState(activePath) { window.sessionStorage.setItem('activePath',activePath) this.activePath = activePath }
Then add an activePath binding data to the data and set the default-active property of el-menu to activePath
Finally in created
created(){ this.getMenuList() this.activePath = window.sessionStorage.getItem('activePath') },
9. Draw the basic structure of the user list
A. Complete the top navigation path using the element-ui crumb component (copy the crumb code, import the component Breadcrumb, BreadcrumbItem in element.js)
B. Use the element-ui card component to complete the body table (copy the card component code, import the component card in the element.js), and then use the element-ui input box to complete the search box and search buttons.
At this point we need to use a raster layout to divide the structure (copy the card component code, import the component Row, Col in element.js), and then use el-button to make the Add User button
<div> <h3>User List Component</h3> <!-- Crumb navigation --> <el-breadcrumb separator="/"> <el-breadcrumb-item :to="{ path: '/home' }">home page</el-breadcrumb-item> <el-breadcrumb-item>user management</el-breadcrumb-item> <el-breadcrumb-item>User List</el-breadcrumb-item> </el-breadcrumb> <!-- Card View Area --> <el-card> <!-- Search and Add Areas --> <el-row :gutter="20"> <el-col :span="7"> <el-input placeholder="Please enter content"> <el-button slot="append" icon="el-icon-search"></el-button> </el-input> </el-col> <el-col :span="4"> <el-button type="primary">Add User</el-button> </el-col> </el-row> </el-card> </div>
10. Request user list data (you can leave a message if needed, depending on the api interface documentation)
<script> export default { data() { return { //Parameters to obtain query user information queryInfo: { query: '', pagenum: 1, pagesize: 2 }, //Save the user list data requested back userList:[], total:0 } }, created() { this.getUserList() }, methods: { async getUserList() { //Send a request to get user list data const { res: data } = await this.$http.get('users', { params: this.queryInfo }) //Error and return if return status is abnormal if (res.meta.status !== 200) return this.$message.error('Failed to get user list') //If the return status is normal, save the requested data in the data this.userList = res.data.users; this.total = res.data.total; } } } </script>
11. Show user list data
Use tables to display user list data, use element-ui table component to complete list display data (copy table code, import component Table, TableColumn in element.js)
When rendering the presentation state, the domain slot is used to get the data for each row
Then use the switch switch switch component to display status information (copy the switch component code and import the component switch in element.js)
When rendering operation columns, scope slots are also used to render them.
The action column contains the Modify, Delete, Assign Roles button when we hover over the Assign Roles button
Hopefully there will be some text prompts, at this point we need to use the text prompt component (copy the text prompt component code, import the component Tooltip in element.js) to include the Assign Roles button
<!-- User List(form)region --> <el-table :data="userList" border stripe> <el-table-column type="index"></el-table-column> <el-table-column label="Full name" prop="username"></el-table-column> <el-table-column label="mailbox" prop="email"></el-table-column> <el-table-column label="Telephone" prop="mobile"></el-table-column> <el-table-column label="role" prop="role_name"></el-table-column> <el-table-column label="state"> <template slot-scope="scope"> <el-switch v-model="scope.row.mg_state"></el-switch> </template> </el-table-column> <el-table-column label="operation" width="180px"> <template slot-scope="scope"> <!-- modify --> <el-button type="primary" icon="el-icon-edit" size='mini'></el-button> <!-- delete --> <el-button type="danger" icon="el-icon-delete" size='mini'></el-button> <!-- Assign Roles --> <el-tooltip class="item" effect="dark" content="Assign Roles" placement="top" :enterable="false"> <el-button type="warning" icon="el-icon-setting" size='mini'></el-button> </el-tooltip> </template> </el-table-column> </el-table>
12. Paging User List
A. Use tables to display user list data, and use the paging component to complete the list paging display data (copy the paging component code and import the component Pagination in element.js)
B. Change binding data in components
<!-- Paging Navigation Area @size-change(pagesize Trigger on change) @current-change(Triggered when page number changes) :current-page(Set Current Page Number) :page-size(Set the number of data bars per page) :total(Set Total Pages) --> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="queryInfo.pagenum" :page-sizes="[1, 2, 5, 10]" :page-size="queryInfo.pagesize" layout="total, sizes, prev, pager, next, jumper" :total="total"> </el-pagination>
C. Add event handlers for two events @size-change, @current-change
//Listen for pagesize change events handleSizeChange(newSize) { // console.log(newSize); this.queryInfo.pagesize = newSize this.getUserList(); }, //Listen for page number value change events handleCurrentChange(newPage) { // console.log(newPage); this.queryInfo.pagenum = newPage this.getUserList(); },
13. Update user status
When a user clicks on the switch component in the list, the user's state should change with it.
A. First listen for user clicks on the switch component and pass the data from the scope slot as an event parameter
<el-switch v-model="scope.row.mg_state" @change="userStateChanged(scope.row)"></el-switch>
B. Send changes to request completion status in an event.
//Listen for changes in switch state async userStateChanged(userinfo) { console.log(userinfo); const {data:res} = await this.$http.put(`users/${userinfo.id}/state/${userinfo.mg_state}`) if(res.meta.status !==200) { row.mg_state = !row.mg_state return this.$message.error('Failed to modify state!') } this.$message.success('Update Status Successful') }
14. Implement search
Add data binding v-model, add click event of search button (call getUserList method to re-request user list data based on text box content when user clicks search button)
When we enter the content in the input box and click Search, we will search by the search keyword. We want to be able to provide an X to delete the search keyword and retrieve all the user list data. Just add the clearable attribute to the text box and the clear event, and request the data again in the clear event.
<!-- Search and Add Areas --> <el-row :gutter="30"> <el-col :span="9"> <el-input placeholder="Please enter content" v-model="queryInfo.query" clearable @clear='getUserList'> <el-button slot="append" icon="el-icon-search" @click="getUserList"></el-button> </el-input> </el-col> <el-col :span="4"> <el-button type="primary">Add User</el-button> </el-col> </el-row>
15. Implement Add Users
A. When we click the Add User button, a dialog box pops up to add users. First, we need to copy the code of the dialog box components and at element. Introducing Dialog components into JS files
B. Next we'll add a click event for the Add User button, where addDialogVisible is set to true, which displays the dialog box
C. Change the content in the Dialog component
<!-- Add User Dialog --> <el-dialog title="Add User" :visible.sync="addDialogVisible" width="50%" @close="addDialogClosed" > <!-- Content Theme Area --> <el-form :model="addForm" status-icon :rules="addFormRules" ref="addFormRef" label-width="70px"> <el-form-item label="User name" prop="username"> <el-input v-model="addForm.username" autocomplete="off"></el-input> </el-form-item> <el-form-item label="Password" prop="password"> <el-input v-model="addForm.password" autocomplete="off"></el-input> </el-form-item> <el-form-item label="mailbox" prop="email"> <el-input v-model="addForm.email" autocomplete="off"></el-input> </el-form-item> <el-form-item label="Mobile phone" prop="mobile"> <el-input v-model="addForm.mobile" autocomplete="off"></el-input> </el-form-item> </el-form> <!-- Bottom Zone --> <span slot="footer" class="dialog-footer"> <el-button @click="addDialogVisible = false">Cancel</el-button> <el-button type="primary" @click="addUser">Determine</el-button> </span> </el-dialog>
D. Add data binding and validation rules:
Mailboxes and mobile phones are validated with regular expressions using the method of creating new objects as follows
data() { //Rules for validating mailboxes var checkEmail = (rule, value, cb) => { const regEmail = /^\w+@\w+(\.\w+)+$/ if (regEmail.test(value)) { return cb() } //Return an error prompt cb(new Error('Please enter a valid mailbox')) } //Rules for verifying mobile phone numbers var checkMobile = (rule, value, cb) => { const regMobile = /^1[34578]\d{9}$/ if (regMobile.test(value)) { return cb() } //Return an error prompt cb(new Error('Please enter a valid mobile number')) } return { //Parameters to obtain query user information queryInfo: { // Query Conditions query: '', // Current number of pages, that is, page number pagenum: 1, // Number of data bars per page pagesize: 2 }, //Save the user list data requested back userList: [], total: 0, //Whether to display the Add User pop-up window addDialogVisible: false, // Add User's Form Data addForm: { username: '', password: '', email: '', mobile: '' }, // Add Validation Rule Object for Form addFormRules: { username: [ { required: true, message: 'Please enter a user name', trigger: 'blur' }, { min: 3, max: 10, message: 'User name at 3~10 Between characters', trigger: 'blur' } ], password: [ { required: true, message: 'Please input a password', trigger: 'blur' }, { min: 6, max: 15, message: 'User name at 6~15 Between characters', trigger: 'blur' } ], email: [ { required: true, message: 'Please enter your mailbox', trigger: 'blur' }, { validator:checkEmail, message: 'Mailbox format is incorrect, please re-enter', trigger: 'blur'} ], mobile: [ { required: true, message: 'Please enter your mobile number', trigger: 'blur' }, { validator:checkMobile, message: 'Incorrect mobile number, please re-enter', trigger: 'blur'} ] } } }
E. Reset the form when closing the dialog
Add the @close event to el-dialog and the code to reset the form to it
methods:{ .... addDialogClosed(){ //After the dialog closes, reset the expression this.$refs.addFormRef.resetFields(); } }
F. Click the OK button in the dialog box to send a request to complete adding the user
First add a click event to the OK button to complete the business logic code in the click event
methods:{ .... addUser(){ //Click the OK button to add a new user //Call validate for form validation this.$refs.addFormRef.validate( async valid => { if(!valid) return this.$message.error("Please fill in the complete user information"); //Send a request to complete adding users const {data:res} = await this.$http.post("users",this.addForm) //Judge that if adding fails, prompt if (res.meta.status !== 200) return this.$message.error('Failed to add user') //Add Success Tips this.$message.success("Successfully added user") //close dialog boxes this.addDialogVisible = false //Re-request the latest data this.getUserList() }) } }