文章目录
前言
ヽ(✿゚▽゚)ノ
现在是2022年的9月28日,
毕业之后的我了解到了公司的一些开发技术,在学校里接触不多甚至几乎没有当然是处处碰壁,
但在其中也是学到了一点东西,可无法灵活的运用
关于前后端交互这块,陌生的就像第一次吃螃蟹
于是 在临近国庆期间 我便在网上找了一些Vue axios的实战项目来析毫剖厘
希望自己的技术能得到一些提升。
商城后台管理系统_日志
一、需要安装的环境

直接npm i +‘名字’
二、项目文件夹结构
目前的了解

>database
是配置的数据库,我使用的是Wampserver32进行配置。
>dist
执行npm run build 打包的项目。
>node_modules
安装的各种依赖。
>public

公用文件。这里的UEditor是一个富文本编辑器就像写评论的那个效果。
>server

连接数据库,配置一些页面接口。
upload里存放的是上到数据库的文件。
config.js是配置文件。
index.js写了跨域的一些内容。
mysql.js是连接的数据库。
router.js是路由跳转用于控制判断是否为数据库里的数据,例如登录判断。
>src

主要操作的地方,组件的增加修改等都在这个文件夹里操作。
base.js是网络请求的地址
index.js是网络请求的方法,例如
assets: 放置静态资源,包括公共的 css 文件、 js 文件、iconfont 字体文件、img 图片文件 以及其他资源类文件。
components: 放置通用模块组件,避免重复工作。
那个js文件夹应该是放在assets文件夹下的。
echarts.js是一个数据可视化的组件。
element.js是引入的elementUI组件。
i18n.js是实现中英语言切换的组件。
router: index.js放置路由设置文件。
封装好的vuex结构。
公共方法汇总。例如我在request.js这里配置了一个请求时的状态码。
各种页面。
剩余的
App.vue: 入口组件,pages 里的组件会被插入此组件中,此组件再插入 index.html 文件里,形成单页面应用。
main.js:入口 js 文件,影响全局,作用是引入全局使用的库、公共的样式和方法、设置路由等。.
register-service-worker.js:用来做离线缓存等任务的,如果在线上,只要访问过一次该网站,以后即使没有网络也可以访问(此时使用的是之前缓存的资源)。
.browserslistrc:配置兼容浏览器。
" >1%" :代表着全球超过1%人使用的浏览器
“last 2 versions” : 表示所有浏览器兼容到最后两个版本
“not ie <=8” :表示IE浏览器版本大于8(实则用npx browserslist 跑出来不包含IE9 )
“safari >=7”:表示safari浏览器版本大于等于7
gitignore:忽略某个或一组文件git提交的一个配置。
babel.config.js:主要作用是将ECMAScript 2015+ 版本的代码,转换为向后兼容的JS语法,以便能够运行在当前和旧版本的浏览器或其它环境中。Vue项目中普遍使用ES6语法,若要求兼容低版本浏览器,就需要引入Babel,将ES6转换为ES5。
package-lock.json:是在npm install执行的时候生成的一份文件,用来记录package.json的来源和版本号。锁住package.json的来源和版本号,多人开发拉取代码,执行npm install生成node_modules时依赖的版本能保持一致。package-lock.json一般要提交到git仓库。
package.json:通过命令生成的vue项目就包含package.json,这是vue项目的表述文件,依赖包就是根据package.json来安装的。
README.md:内容相关的解释。
sh.exe.stackdump:啊这,这是个啥。似乎是使用git命令后出现的。
vue.config.js:是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。我在这里设置了api的接口网址。
三、页面搭建 (可能遇到的问题)
= ̄ω ̄=
1、 Login页面分析
先上源码
<template>
<div class="login">
<el-tabs
v-model="activeName"
type="border-card"
class="login-tabs"
stretch
@tab-click="handleClick"
>
<el-tab-pane label="用户登陆" name="login" class="login-tabs-tab">
<el-form
ref="loginForm"
:model="user"
status-icon
:rules="rules"
class="login-form"
>
<el-form-item label="用户名" prop="username">
<el-input type="text" v-model="user.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="user.password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('loginForm')">登陆</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="用户注册" name="register">
<el-form
ref="registerForm"
:model="user"
status-icon
:rules="rules"
class="login-form"
>
<el-form-item label="用户名" prop="username">
<el-input type="text" v-model="user.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="user.password"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="surePassword">
<el-input type="password" v-model="user.surePassword"></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input type="email" v-model="user.email"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('registerForm')">注册</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import { mapActions } from "vuex"
export default {
name: "Login",
data() {
var validateUsername = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入用户名"));
}
callback();
};
var validatePassword = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入密码"));
}
callback();
};
var validateSurePassword = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入密码"));
}
callback();
};
var validateEmail = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入邮箱"));
}
callback();
};
return {
user: {
username: "",
password: "",
surePassword: "",
email:""
},
rules: {
username: [{ validator: validateUsername, trigger: "blur" }],
password: [{ validator: validatePassword, trigger: "blur" }],
email: [{ validator: validateEmail, trigger: "blur" }],
surePassword: [
{ validator: validateSurePassword, trigger: "blur" },
],
},
activeName: "login",
};
},
methods: {
...mapActions("loginModule",["setUserActions"]),
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
/**
* 区分是登陆还是注册
*/
if (this.activeName === "login") {
/**
* 登陆
*/
this.setUserActions(this.user)
}
if (this.activeName === "register") {
/**
* 注册
*/
this.$api.register({
username:this.user.username,
password:this.user.password,
email:this.user.email
}).then(res =>{
console.log(res.data)
})
}
} else {
console.log("error submit!!");
return false;
}
});
},
handleClick(tab, event) {},
},
};
</script>
<style scoped lang="less">
.login {
width: 500px;
margin: 0 auto;
margin-top: 100px;
.login-form {
padding: 40px 40px;
}
h3 {
margin-top: 20px;
}
.login-tabs {
border-radius: 5px;
}
}
</style>
先从布局来说吧
根标签
的类名是login,用于控制这个页面的大小以及位置。
el-tabs
引用的是elementUI的tabs标签页,包括那些定义在标签上的属性详情见链接。
el-tabs
引用的是elementUI的form表单。
el-input
引用的是elementUI的input输入框。注意这里的prop和v-model=“user.username”,都是传入 Form 组件的 (:model=“user”)user 中的字段。
el-button
引用的是elementUI的button按钮。
script里的内容
mapActions
就是将组件中的事件函数映射为对应的action,其中事件函数名称与action名称应该是一样的。
name
这里稍微提一下吧,我在写的时候,必须用到LoginVue这样的驼峰写法,不然报错。每个组件最好是写上他的name属性。
rules
这里是一个elementUI form表单的一个验证规则的属性,写成了一个函数有三个参数,rule是验证,value是值,callback是回调函数。rules写在data return对象里。
mapActions方法
>
来源于vuex的store文件夹下的modules的login~.js中的setUserActions方法。登录成功时执行的操作。
顺带一提登录失败时,是写在了utils公共方法文件夹下的request.js里
本页面的核心 submitForm方法
该方法绑定在
可以知道标签里写的‘loginForm’的字符串数据被methods里的formName接受,用于判断提交的是哪里的数据。然后通过elementUI tab组件自带的一个handleClick方法获取el-tab-pane标签上的name属性,以此来判断点击的是登录还是注册(具体在这),判断完之后就可以执行操作了。
如果是登录 执行了上面的setUserActions方法。
如果是注册 这里是用到了axios封装好的api接口。
最后CSS
稍微做了一些修饰。
效果

2、 导航栏组件分析
先上源码
<template>
<el-menu
:default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
router
>
<el-menu-item index="/"><i class="el-icon-menu"></i>{{ $t("message.project") }}</el-menu-item>
<el-menu-item index="/params"><i class="el-icon-document"></i>{{ $t("message.params") }}</el-menu-item>
<el-menu-item index="/content"><i class="el-icon-setting"></i>{{ $t("message.content") }}</el-menu-item>
<div class="user">
<router-link to="/user" tag="span" class="user-name">{{ user.username }}</router-link>
<el-button class="logout" @click="logoutHandle">退出</el-button>
</div>
<el-menu-item class="set-lang">
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
语言环境
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="zh">中文</el-dropdown-item>
<el-dropdown-item command="en">英文</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-menu-item>
</el-menu>
</template>
<script>
import { mapState, mapMutations } from "vuex";
import local from "../../utils/lcoalUtils";
import i18n from "../../plugins/i18n"
export default {
name: "NavMenu",
data() {
return {
activeIndex: "/",
};
},
computed: {
...mapState("loginModule", ["user"]),
},
mounted() {
if (sessionStorage.getItem("path")) {
this.activeIndex = sessionStorage.getItem("path");
}
},
methods: {
...mapMutations("loginModule", ["removeUser"]),
handleSelect(key, keyPath) {
if(key){
sessionStorage.setItem("path", key);
}
},
logoutHandle() {
/**
* 本地清除
* 状态清除
* 回到登录页
*/
local.removeLocal("ego");
this.removeUser();
this.$router.push("/login");
},
/**
* 切换语言环境
*/
handleCommand(command){
i18n.locale = command
}
},
};
</script>
<style scoped lang="less">
.user {
float: right;
margin-right: 20px;
line-height: 60px;
.user-name {
color: #fff;
margin-right: 10px;
font-size: 15px;
border: 1px solid #fff;
border-radius: 50%;
width: 40px;
height: 40px;
display: inline-block;
line-height: 40px;
}
.logout {
}
}
.set-lang {
float: right !important;
}
.el-dropdown-link {
color: #fff;
}
</style>
先从布局来说吧
el-menu
elementUI的导航菜单组件。
用户个人中心
使用的router to跳转。
el-dropdown
elementUI的下拉菜单。
script里的内容
import引入的
mapState:vuex的东西,获取多个状态的时候使用。在计算属性里使用。这里是获取了‘user’。
mapMutations:vuex的mutation的辅助函数,用于在组件中映射mutation内的方法,以便在该组件中直接使用mutation里的方法。
local:地址状态。
i18n:语言环境配置。
data里的数据
这里的activeIndex对应el-menu标签上default-active当前激活菜单的 index绑定的。
sessionStorage
跨页面传数据的时候就经常能用到它,用来传id传状态,传一些样式数据都可以。在mounted()里使用。
methods里的方法
handleSelect方法是elementUI里的。
最后CSS
注意级别问题吧,使用!important解决。
效果

四、EventBus 组件通信
使用方法
1、
在utils(公共方法汇总)文件夹下创建eventbus.js。
2、写入的代码内容:
import Vue from "vue"
const EventBus = new Vue();
Object.defineProperties(Vue.prototype,{
$bus:{
get:function(){
return EventBus
}
}
})
3、发送数据
this.$bus.$emit("onParamsSearch",res.data.result);
//引号里的为参数名,后面是发送的数据
4、接受数据
this.$bus.$on("onParamsSearch", (result) => {
this.paramsData = result;
});
//引号里的为参数名,后面是接受的数据result(这个可以自定义名字res也没问题),
//后面的就是把接收到的数据赋给当前组件里的数据名。
完毕
这个方法是任意组件的通信,还是很方便的。知识+1.
五、模糊查询 实现
布局

elementUI组件:输入框和按钮。
查询的方法
当前组件下

api文件夹下


server文件夹下

最后list列表组件接收查询数据 渲染视图

就我的了解。输入框里的内容不为空时执行 api index.js里封装的
这个方法,其中base.baseUrl等是api base.js里封装的路径。然后把输入的内容赋给了search这个参数,接下来判断状态码是否为200,如果是则发送输入的数据所查询到的列表,不是就发送空数组。查询是在server router.js里的
查询。然后list组件接受渲染。嗯…
六、自己尝试写了一个留言功能
成功了
总结
~(~ ̄▽ ̄)~
先写到这吧,这个项目还有看完,而且该吃晚饭了。
2022/9/28 19:55
login的页面就是这样了,虽然看着简单,但如果没有指导的话,在api接口和server配置连接数据库还有store、utils这里自己写还是有亿点难度的。就目前情况来看,通过看源码尝试理解代码逻辑结构,还是勉强可以的,接下来我会自己添加一些页面以及功能。
NavMenu导航栏组件解决。准备构建首页页面。
2022/9/30 15:21
首页已经跟着写完了,新了解的有:
“:class=“{box:true,boxmargin: index % 2==0 ? true : false}” v-for”三元表达式来判断类名的应用;
“v-if=“item.hot= =true”>HOT”通过在循环列表中设置数据配合v-if来决定高亮hot显示;
还有一个三级路由显示,倒也没什么 就是在app的view视图下的homeindex的view视图下的detail的view视图下显示的内容。
效果图也比较简单就不上传了。
今天是有了解到EventBUS的一个方法实现组件通信,还有模糊查询的实现 有点懵,还是不熟练。elementUI倒是看的很熟练了。
2022/10/2 19:33
自己做了一个留言功能,发送的数据保存在数据库的一个表中,然后再渲染出来,不可思议 我成功了,明天再解决页码显示条数的问题。
2022/10/3 22:23



















>













