文章目录
- 注意本文只是一个简单框架,可以实现相应功能但是内容和样式需要自己补充
1. 屏幕宽度监听,控制样式改变(顶部导航栏的样式)
应用小场景 : 有自适应布局时,顶部导航栏随屏幕宽度变化无法满足功能和美观的要求。
实现效果 : 手机宽度屏 与 电脑宽度屏
代码如下
<template>
//v-if v-else 方法
<div class="bigtop" v-if="show == true">这里写电脑宽屏时的顶部导航栏 </div>
<div class="smalltop">这里写手机窄屏时的顶部导航栏 </div>
</template>
<script>
export default {
//返回值show
data(){
return{
screenWidth:window.innerWidth, //浏览器宽度
show:true //判断条件
}
}, //监听事件改变数值
mounted(){
const that = this;
window.onresize = ()=>{
return (()=>{
window.screenWidth = window.innerWidth
that.screenWidth = window.screenWidth;
})()
}
},
watch: {
screenWidth(val) {
this.screenWidth = val
console.log(this.screenWidth)
if(this.screenWidth<1000){
this.show = false
}else{
this.show = true
}
}
}
}
</script>
<style scoped>
//不同屏幕宽度下的顶部导航栏样式
.bigtop{
}
.smalltop{
}
</style>
2. 监听滚动事件,滚动距离改变组件出现与否(下滑一段距离侧边出现小窗口)
应用小场景 :侧边栏向下在滚动一定距离时出现的小窗口
实现效果 :类似优快云 首页持续下滑,到达一定程度,出现的窗口,并且固定显现不动。 小窗口内容效果展示
代码实现
<template>
<div class="block" v-show="showFixedSearch">这里写出现的小窗口内容 </div>
</template>
<script>
export default {
data(){
return{
showFixedSearch: false, }
}
mounted() {
// 监听页面滚动事件
window.addEventListener("scroll", this.showSearch)
},
methods:{
showSearch() {
// 获取当前滚动条向下滚动的距离
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
// 当页面滚动到高度800px处时,显示搜索框
if (scrollTop > 800) {
this.showFixedSearch = true;
} else {
this.showFixedSearch = false;
}
}
}
</script>
<style scoped>
//弹窗样式
.block{
}
</style>
3. 根据缓存用户名,改变用户登录样式(用户未登录是“登录/注册”字样,用户已登录是用户头像图片)
应用小场景 : 登录或者注册后,字样变为用户头像。
实现效果 :
代码实现
<template>
// @click 点击事件的方法 判断是否登录
// v-if v-else 改变用户登入后的样式
<div class="nav_span" @click="if_login" v-if="username==null">
<h3>登陆/注册</h3>
</div>
<div v-else>
<el-dropdown>
<span class="el-dropdown-link">
<!-- <img src="这里写头像的链接"> -->
<img src="https://img1.baidu.com/it/u=3921673502,2542489910&fm=26&fmt=auto" style="border-radius: 50%;width: 55px;height: 55px;">
</span>
<el-dropdown-menu slot="dropdown">
// @click 点击事件 退出登录,清除用户登录缓存
<span @click="user_quit">
<el-dropdown-item><i class="el-icon-back"></i>退出</el-dropdown-item>
</span>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<script>
export default {
//打印缓存的用户名
created() {
const that=this;
that.username= sessionStorage["username"]
console.log( that.username)
},
//初始化用户名为空
data(){
return{
username:null,
}
},
methods:{
//退出登录,清除用户名缓存
user_quit(){
sessionStorage.removeItem('username');
},
}
}
4. 仿弹窗式的登录页面(父子路由,背景半透明)
应用小场景 :实现弹窗式登录小窗口效果,非弹窗是新页面,涉及父子路由
实现效果 : 在父页面上展示子页面,子页面设置背景颜色半透明的灰色,顶牛版效果展示
代码实现
//父页面 底部背景页面
<el-main>
<div class="main_body" style="width:100%;position: absolute; top:60px;left:1px; ">
<router-view></router-view>
</div>
</el-main>
index.js
{
path: '/',
name: 'home',//父页面
component: home, //父页面顶部导航栏
redirect:home_main, //父页面主要内容
children:[ //子页面
{
path: '/home_main',
name: 'home_main',
component: home_main,
},
{
path: '/login',
name: 'login',
component:login
},
]
登录子页面
<template>
<div id="login"class="body">
//表单登录组件
<el-card class="card">
<span class="title">团队管理系统</span>
<el-form :model="loginform" :rules="loginrules" ref="loginform">
<el-form-item label="账号" prop="username">
<el-input v-model="loginform.username" placeholder="请输入登陆账号" class="username" @keyup.enter.native="submitForm('loginform')">
</el-input></el-form-item>
<el-form-item label="密码" prop="password">
<el-input placeholder="请输入用户密码" v-model="loginform.password"
@keyup.enter.native="submitForm('loginform')"show-password class="password">
</el-input></el-form-item>
<el-button type="primary" class="login_button" @click="submitForm('loginform')">登陆</el-button>
<router-link to="register">
<el-button id="loginbutton" type="primary" class="login_button" >注册</el-button></router-link>
// 清除用户名缓存
<p class="close" @click="close">×</p>
</el-form>
</el-card>
</div>
</template>
<script>
export default {
name: "login",
data() {
return {
publicKey:'',
loginform: {
username: '',
password: '',
},
loginrules: {
username: [
{required: true, message: '请输入账号', trigger: 'blur'},
{min: 1, max: 20, message: '长度在 1 到 15 个字符', trigger: 'blur'}
],
password: [
{required: true, message: '请输入密码', trigger: 'blur'},
{min: 0, max: 20, message: '长度在 0 到 20 个字符', trigger: 'blur'}
]
}
}
},
methods: {
submitForm(formName) {
//缓存用户名
sessionStorage.setItem('username',this.loginform.username);
this.$refs[formName].validate((valid) => {
if (valid) {
const _this= this
_this.$axios.get('/publicKey')
.then((response)=>{
const sm2 = require('sm-crypto').sm2
const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1
_this.publicKey=response.data
let encryptData = sm2.doEncrypt(_this.loginform.password, _this.publicKey, cipherMode) // 加密结果
_this.$axios.post('/login',_this.$qs.stringify({
password:encryptData
})
)
.then((response)=>{
})
})
// let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) // 解密结果
//给后端传值时需要在加密的密文前面加04 (`04${encryptData}`),这样后端才能解密正确不报错
console.log('登陆成功!!');
_this.$router.push({
path:'/',
})
} else {
console.log('登陆失败!!');
return false;
}
});
},
close() {
//清除缓存中的用户名
sessionStorage.removeItem('username');
this.$router.push('/');
},
}
}
</script>
<style>
.el-form-item__label{
color: black;
}
</style>
<style scoped>
.close{
font-size:25px;
position: absolute;
top:0;
right: 20px;
cursor: pointer;
}
#login{
height: 100vh;
}
//背景颜色透明度
.body{
width:100%;
height:100%;
position:fixed;
left:0;
top:-1%;
background-size: 100% 110%;
background: #000;
opacity: 0.5;//透明度
}
.card{
width:400px;
height: 400px;
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
padding: 10px;
background: url("https://img2.baidu.com/it/u=3562887657,1354757817&fm=26&fmt=auto");
box-sizing: border-box;
box-shadow: 0 15px 25px rgba(0,0,0,.5);
border-radius: 10px;
}
.username{
margin-top: 5%;
}
.password{
margin-top: 5%;
}
.login_button{
width: 30%;
margin-top: 10%;
background-color: #008b8b;
}
.title{
font-family: 华文楷体;
font-size: 20px;
margin: 20px;
}
</style>
5. 个人信息修改页面(用户头像上传,限制仅可一张,头像可预览,可删除)(开关按钮双向绑定控制输入框的禁用与否)
应用小场景 :上传用户头像,限制仅可一张,且可预览和删除;开关按钮双向绑定控制输入框的禁用与否,编写用户信息
实现效果
代码实现
<template>
<div id="edit">
<el-form>
//用户头像上传
<el-upload
:limit="1" //限制仅可上传一张
action
accept="image/*"
:on-change="uploadFile"
list-type="picture-card"
:auto-upload="false"
:file-list="fileList"
:on-exceed="handleExceed"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
ref="upload"
class="avatar-uploader"
:class="{hide:showUpload}"
:disabled="disabled"
>
<i class="el-icon-user-solid"></i>
</el-upload>
<el-dialog width="205" :visible.sync="dialogVisible">
<h3>头像浏览</h3>
<img width="80%" :src="imgUrl.url" class="imgs" alt />
</el-dialog>
</el-form>
<el-form :model="userform" :rules="userrules">
//按钮开关控制输入框的禁用于否
// @change="isDisabled" 按钮绑定
<el-form-item class="switch">
<el-switch v-model="value" @change="isDisabled" :inactive-text="编辑" :active-text="完成"></el-switch>
<span >编辑</span>
</el-form-item>
<el-form-item class="font1" prop="name"><span>用户昵称:</span>
<el-input v-model="userform.name" class="font2"
//:disabled="isdisabled" 输入框绑定
:disabled="isdisabled"></el-input></el-form-item>
<el-form-item class="font1"><span>用 户 I D:</span><el-input :disabled="isdisabled" class="font2" v-model="userform.ID"></el-input></el-form-item>
<el-form-item class="font1" prop="introduction"><span>个人简介:</span><el-input class="font2":disabled="isdisabled"v-model="userform.introduction">
</el-input></el-form-item>
<div class="font1"><span>所在地区:</span><el-input :disabled="isdisabled" class="font2" v-model="userform.region"></el-input></div>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "edit",
props: {
limit: Number,
fileList: Array,
disabled: Boolean,
},
data() {
return {
showUpload: false, //控制limit最大值之后 关闭上传按钮
dialogVisible: false, //查看图片弹出框
imgUrl: [], //上传图片后地址合集
isdisabled:true,
fileList: [ ],
userform:{
name:'jhon',
sex: '1',
ID:'winxin_885155',
introduction:'',
birth:'Mon Apr 12 2021 00:00:00 GMT+0800 (中国标准时间)',
region:'',
},
userrules:{
name: [
{required: true, message: '请输入用户昵称', trigger: 'blur' },
{ min: 1, max: 10, message: '长度在 1 到 10 个字符', trigger: 'blur' }
],
introduction:[
{ min: 0, max: 20, message: '长度在 0 到 20 个字符', trigger: 'blur' }
]
}
};
},
watch: {
fileList(newName, oldName) {
if (newName.length == this.limit) this.showUpload = true;
else this.showUpload = false;
},
},
methods: {
isDisabled(){
this.isdisabled = !this.isdisabled;
this.$emit('change',event)
},
//文件列表移除文件时的函数
handleRemove(file, fileList) {
const index = this.fileList.findIndex((item) => item === file.uid);
this.imgUrl.splice(index, 1);
this.$emit("delUrl", this.imgUrl);
if (fileList.length < this.limit) this.showUpload = false;
},
//点击文件列表中已上传的文件时的函数
handlePictureCardPreview(file) {
this.imgUrl.url = file.url;
this.dialogVisible = true;
},
//这里是不需要直接上传而是通过按钮上传的方法
submitUpload() {
this.$refs.upload.submit();
},
//文件状态改变时的函数(主要逻辑函数)
uploadFile(e, fileList) {
//判断用户上传最大数量限制,来让上传按钮消失
if (fileList.length >= this.limit) this.showUpload = true;
// const file = e.file; <- 这里是不需要直接上传而是通过按钮上传的
const file = e.raw; // <- 这里是直接上传的
//大小
const size = file.size / 1024 / 1024 / 2;
if (
!(
file.type === "image/png" ||
file.type === "image/gif" ||
file.type === "image/jpg" ||
file.type === "image/jpeg"
)
) {
this.$notify.warning({
title: "警告",
message:
"请上传格式为image/png, image/gif, image/jpg, image/jpeg的图片",
});
} else if (size > 2) {
this.$notify.warning({
title: "警告",
message: "图片大小必须小于2M",
});
} else {
if (this.limit == 1) this.imgUrl = []; //此处判断为一张的时候需要清空数组
const params = new FormData();
params.append("source", file);
uploadImg(params).then((res) => {
//这里返回的数据结构(根据自己返回结构进行修改)
if (res.data.status === 1) {
this.$message.success("上传成功");
this.imgUrl = res.data;
//调用父组件的方法来传递图片参数
this.$emit("getUrl", this.imgUrl);
} else this.$message.error("上传失败");
});
}
},
//文件超出个数限制时的函数
handleExceed(files, fileList) {
// this.$message.info(`最多只允许上传${this.limit}张图片`);
this.$message.info(`用户头像最多只允许上传1张图片`);
},
}
}
</script>
<style scope> //更改组件样式有效
#edit{
width: 80%;
margin: auto;
}
.el-input.is-disabled .el-input__inner{
color: rosybrown;
}
.avatar-uploader .el-upload {
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader > .el-upload > i {
font-size: 25px;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader > .el-upload-list > .el-upload-list__item {
width: 100px;
height: 100px;
margin-top: 5%;
border-radius: 50%;
}
.avatar-uploader > .el-upload-list > .el-upload-list__item > img {
width: 100px;
height: 100px;
margin-top: 5%;
border-radius: 50%;
}
.avatar-uploader > .el-upload {
width: 100px;
height: 100px;
margin-top: 5%;
border-radius: 50%;
border: 1px dashed #ccc;
}
.imgs{
width: 150px;
height: 150px;
margin-top: 5%;
}
.hide .el-upload--picture-card {
display: none !important;
}
.switch{
margin-left: 50%;
}
.el-radio {
color: #606266;
font-weight: 500;
cursor: pointer;
margin-right: 10%;
/*margin-left: 1%;*/
}
.font1{
color: black;
margin-top: 30px;
}
.font2{
width: 40%;
margin-left: 5%;
}
.font3{
color: black;
margin-top: 30px;
}
</style>
后记
此项目是根据学长学姐已完成整个项目的基础上进行改写,因此,里面涉及到一些请求get/post 的后端接口可能影响功能效果实现,把接口给为自己的后端接口,即可。
在此记录下,添加或者完善的一些功能以及样式特色1
对我来说,内容很多,且意义大,在此记录以防忘记。加油,(ง •_•)ง ! ↩︎