记录VUE项目中的一些小亮点(自学)

  • 注意本文只是一个简单框架,可以实现相应功能但是内容和样式需要自己补充

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. 监听滚动事件,滚动距离改变组件出现与否(下滑一段距离侧边出现小窗口)

应用小场景 :侧边栏向下在滚动一定距离时出现的小窗口
实现效果 :类似CSDN 首页持续下滑,到达一定程度,出现的窗口,并且固定显现不动。 小窗口内容效果展示
在这里插入图片描述
代码实现

<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: '长度在 115 个字符', trigger: 'blur'}
        ],
        password: [
          {required: true, message: '请输入密码', trigger: 'blur'},
          {min: 0, max: 20, message: '长度在 020 个字符', 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: '长度在 110 个字符', trigger: 'blur' }
        ],
        introduction:[
          { min: 0, max: 20, message: '长度在 020 个字符', 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


  1. 对我来说,内容很多,且意义大,在此记录以防忘记。加油,(ง •_•)ง ! ↩︎

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值