自己开发中遇到的问题

1.axios常见传参方式及基本使用

全写【vue3】

1.1 get请求

需要自己配置request.js

axios({
        url:'http://localhost:5000/person',
        method:'GET',
        params:{id:personId.value} 
        # 此处写的是params,但是携带的是query参数 
    }).then(
        response=>{ console.log('请求成功了!',response.data);},
        error=>{console.log('请求失败了!',error);}
    )

1.2 post请求

axios({
        url:'http://localhost:5000/person',
        method:'POST',
        # 1. 携带请求体参数,json编码
        data:{name:personName.value} 
    }).then(
        response=>{ console.log('请求成功了!',response.data);},
        error=>{console.log('请求失败了!',error);}
    )

简写【vue2】

//main.js
//需要全局挂载axios并配置u根路径
import axios from 'axios'
Vue.prototype.$http = axios
axios.defaults.baseURL = 'http://121.41.91.38:8002'

1.1get请求

无参数传递
async getAllMajor() {
            const { data: res } = await this.$http.get('/admin/get_majors')
            if (res.code !== 200) {
                this.$message.error('获取失败')
            } else {
                this.options1 = res.data
            }
        }
有参数传递
async getAllMajor() {
                                                    //get发起请求时如果需要携带参数则用params
      const { data: res } = await this.$http.get('/admin/get_majors',{params:{stu_id:this.stu_id,class:class}})
            if (res.code !== 200) {
                this.$message.error('获取失败')
            } else {
                this.options1 = res.data
            }
        }

1.2post请求

传递参数

//单个参数
async change1(value) {
                                    //这里传递参数需要获取data里面自定义value1中的major
            const { data: res } = await this.$http.post('/admin/get_class', {
                major: this.value1.major
            })
            // console.log(res);
            this.options2 = res.data
        },
 //多个参数
  async change1(value) {
                                    //这里的addForm包含了多个参数,都定义在data中
            const { data: res } = await this.$http.post('/admin/get_class',this.addForm )
            // console.log(res);
            this.options2 = res.data
        },

在请求接口时,在setup中调用接口,使用async await函数,async被省略了

自己开发中遇到的问题_第1张图片

2.当页面缩放的时候,该怎么解决样式崩盘的问题呢?

1.首先,如果只是使用定位的话,当页面缩小的时候是肯定不会保持二者之间的相对距离的,缩放的话样式肯定会崩的。

2.可以尝试给这两个元素(也可能是很多个,具体的看你自己的界面而定)的父元素设定flex布局,然后设置flex常见的几行代码:

display:flex;
//主轴排列方式
justify-content:center;
//单行侧轴排列
aligin-items:center;
//多行侧轴排列
align-content:center

3.你需要显示的内容和父元素大致是这样的关系:

4.最后,你的元素有可能是挤在中间的,这个时候,再去对左边和右边的div进行定位,最好是用相对定位,因为相对定位自己本身的空间还站着,不会脱离文档流,不对其他元素的布局造成影响。

5.等你调好之后,再去缩放浏览器,你就会惊奇的发现,样式不崩了,不管是缩小还是放大,二者之间的距离都是不变的

3.关于登录退出token的设置

登录设置token

window.sessionStorage.setItem('token',res.data.token)

退出登录清除token

window.sessionStorage.removeItem('token')

4.关于使用token进行路由守卫限制

//挂载路由导航守卫
router.beforeEach((to, from, next) => {
  //to 表示要访问的路径
  //from 代表从哪一个路径跳转而来
  //next 是一个函数,表示放行
  //    next()  放行    next('/login') 强制跳转

  if (to.path === '/login') return next();
  //获取token
  const tokenStr = window.sessionStorage.getItem('token')
  //如果没有获取到token那么返回登录
  if (!tokenStr) return next('/login')
  //得到token就跳转页面,放行
  next()
})

5.el-pagination分页组件纯前端分页使用方法

el-pagination分页组件前端分页使用方法

  1. el-table

  ...
  1. el-pagination
  1. data
data() {
  currentPage: 1,  // 当前页码
  pageSize: 10,  // 每页显示的行数
  tableData: [...],  // 表格数据
}
  1. methods
methods: {
  // 页面切换方法
  handleCurrentChange(val) {
    this.currentPage = val;
  }
}

6.css对于图片的处理

1、图片填充DIV容器大小

将DIV的大小设置成为固定的大小,设定img 的宽度为:100%,高度为:100%;即可让图片自动适应DIV容器的大小。

2.指定背景图像的大小:

div
{
    background:url(img_flwr.gif);
    background-size:80px 60px;
    background-repeat:no-repeat;
}

7.让文字垂直居中

display: flex;
align-items:center;

8.box-shadow

链接:box-shadow详解_火兰的博客-CSDN博客

box-shadow 属性接受值最多由五个不同的部分组成。

box-shadow: (offset-x offset-yblurspreadcolorposition) ;

等同于:对象选择器 {box-shadow:X轴偏移量 Y轴偏移量 阴影模糊半径 阴影扩展半径 阴影颜色 投影方式 }

1.offset-x:指明了阴影水平方向的偏移,即阴影在 x 轴的位置。值为正数时,阴影在元素的右侧;值为负数时,阴影在元素的左侧。

2.offset-y:指明了阴影竖直方向的偏移,即阴影在y 轴的位置。值为正数时,阴影在元素的下方;值为负数时,阴影在元素的上方。

3.blur:第三个长度值代表了阴影的模糊半径,值为 0 意味着该阴影是固态而锋利的,完全完全没有模糊效果。blur 值越大,阴影越模糊。负值是不合法的,会被修正成 0。

4.spread第四个长度代表了阴影扩展半径,其值可以是正负值,如果值为正,则整个阴影都延展扩大,若值为负值缩小。前提是存在阴影模糊半径。

5.color:color 部分指阴影的颜色。它可以是任意的颜色单元 (见 在 CSS 中与颜色打交道)

6.position此参数是一个可选值,如果不设值,其默认的投影方式是外阴影;如果取其唯一值“inset”,就是将外阴影变成内阴影,也就是说设置阴影类型为“inset”时,其投影就是内阴影。

9.element

1.数据动态绑定


2.表单校验与表单预检验

vue2

// vue2

vue3

// vue3


          

3.重置表单


10.前端登录时所做的token验证(路由守卫、请求拦截器、响应拦截器)

用户进入网站首次登录,前端会携带用户信息(用户名、密码什么的)到服务端做请求

1、服务端验证用户名密码

未通过校验:响应给前端,用户名/密码错误等信息

通过校验:对该用户创建token,并将token作为响应数据返回给前端

2、前端拿到响应数据:

错误信息:页面给予提示:用户名/密码错误

正常信息:页面进行跳转到首页,保存token(可以保存在cookie或sessionStorage)

3、用户点击触发请求:

【路由守卫】(全局——Vue中的 beforeEach())

判断即将进入的页面需不需要token(例如:路由配置中 meta{authRequired:true})

不需要:next()放行,展示页面

需要:从本地获取token(获取到则发起请求,没获取到则返回登录页引导登录)

router.beforeEach((to, from, next) => {
    //这里是获取token,点击登录时需要将token保存,然后再路由守卫中进行验证
  const token = sessionStorage.getItem('token')
  // 目标路由不是登录页,并且还需要token验证,还没有token,那就直接给返回到登录页
  if (to.name !== 'Login'&& to.meta.authRequired && !token){
      next({ name: 'Login' })
  }else{
      // 目标路由是登录页-自然不需要token验证
      // 或目标路由不需要身份验证
      // 又或目标路由非登录页,需要token验证,但是有token
      // next放行
      next()
  }
})

补充

// 1.将登录成功之后的token,保存到客户端的sessionStorage中
        //      1.1 项目中除了登录或注册之外的其他API接口,必须在登录之后才能访问
        //      1.2 token只应在当前网站打开期间生效,所以将token保存在sessionStorage中
        // localStorage生命周期是永久,这意味着除非用户显示在浏览器提供的UI上清除localStorage信息,否则这些信息将永远存在。
        // sessionStorage生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,那么所有通过sessionStorage存储的数据也就被清空了。
        window.sessionStorage.setItem('token', res.data.token)
        //将res.data.token赋值给sessionStorage中的token
        // 2.通过编程式导航跳转到后台主页,路由地址是 /home
        this.$router.push('/home')

11.axios设置token到请求头【重要】

一.为什么要设置请求头到token?

  • 当输入用户名及密码,登录成功后,后台会返回一个token,在之后发送的请求都要带上这个token,因为后台设置了拦截,如果token一致,则允许访问,否则请求不成功。

二.用法

(1)首先输入账号密码

(2)账号密码验证无误后,服务器会随机生成一个token值(令牌)

(3) 将服务器返回的token值 在我们本地进行存储

自己开发中遇到的问题_第2张图片

(4) 下次登陆时就携带这个token(我们把token值放在http请求头)

(5)最后在退出登陆时,将token在本地化存储中删除

window.sessionStorage.clear();

当状态码时401就说明token校验失败,给予用户提示/跳转到登录页面

大物项目代码展示

async login() {
      const { data: res } = await this.$http.post(
        "/api/users/login",
        this.loginForm
      );

      if (res.code == 200) {
        this.$message.success("登录成功!");
          //将获取到的token存储在sessionStorage
        window.sessionStorage.setItem("token", "Bearer " + res.data.token);
        this.$router.push("/home");
      }
      if (res.code == 100) {
        this.$message.error("登录失败!");
      }
    },

11axios拦截器

HTTP请求头:

X-Requested-With(作用:异步请求)

现在很多的功能都会用到这个异步请求,比如说登录。

//X-Requested-With:它的作用是:异步请求
axios.defaults.headers = {
  'X-Requested-With': 'XMLHttpRequest',
}

异步请求的特点:无刷新。就是说登录的时候是需要进行页面跳转的,而异步请求它不需要跳转也可以做到这样的请求。

//请求拦截器:1.展示loading动画
	   2.认证登录,关于token/cookie
	   3.某些请求参数的转化
//响应拦截器:1.关闭loading动画
			2.对相应的数据机型转化,转化之后再返回

// axios请求拦截器 => interceptors 在页面发送请求前进行一次预处理
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });


 //axios响应拦截器
// use(两个参数)
axios.interceptors.response.use(function (response) {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    return Promise.reject(error);
  });
大物代码展示:
axios.interceptors.request.use((config) => {
        config.headers.Authorization = window.sessionStorage.getItem("token")
        return config
    },
    error => {
        error.data = {
            message: '服务器异常!'
        }
        return Promise.reject(error)
    }
)

12.Flex布局中justify-contnt和align-items属性失效的原因和解决方法

属性失效的原因:因为justify-contnt属性是控制在主轴上的对齐方式,align-items属性是控制侧轴上的对齐方式.所以在首对齐,中对齐,尾对齐等各种对齐效果生效时需要计算组件的宽度。当组件的 主轴长度属性(主轴为横轴时就是width,为纵轴时就是height)没有进行设置时,属于灵活延展的,所以无法进行计算,故属性没有生效。

解决方案:为主轴设置好确切的长度

13.v-for渲染

真实开发的时候,我们往往会从服务器拿到一组数据,并对其进行渲染

把v-for写在谁身上,谁就会出现多个!!!

v-for的基本格式:“item in 数组” ,如果需要拿到索引值,则写成: (item,index)in 数组

  • 数组通常来自于data或prop,也可以是其他方式
  • item 是我们给每一个元素起的别名,这个别名可以自己来定义

人员列表(遍历数组)

    //最好使用每条数据的唯一标识作为key
  • {{item.name}}-{{item.age}}

汽车信息(遍历对象)

  • {{key}}-{{value}}

14.点击事件传参





 

15.组件间的传参

15.1EventBus

推荐:全局事件总线:实现任意组件间的通信

  • 1.在main.js中安装全局事件总线$bus【使用beforeCreate(){}钩子】
//引入Vue
import Vue from 'vue';
//引入App
import App from './App';

//关闭vue的生产提示
Vue.config.productionTip = false

//创建vm
new Vue({
    el: "#app",
    render: h => h(App),
    beforeCreate() {
        Vue.prototype.$bus = this//安装全局事件总线
    }
})
  • 2.接收数据(this.$bus.$on()):school组件想接收数据,则在school组件的mounted中给$bus绑定自定义事件
mounted(){
          this.$bus.$on('hello',this.demo)
        }

3.提供数据(this.$bus.$emit()):student组件去触发事件。比如在Student组件中准备一个按钮,绑定send方法,点击按钮去触发这个事件

 methods:{
        send(){
            this.$bus.$emit('hello',this.name)
        }
    } 

4.解绑数据:最好在beforeDestory(){}钩子中,用$off去解绑当前组件所用到的事件,所以在School组件中去解绑hello事件

beforeDestroy() {
        console.log('hello事件被解绑')
       this.$bus.off('hello')
    },

完整代码:

main.js

import Vue from 'vue'
import App from './App.vue'
 
//关闭vue生产模式
Vue.config.productionTip = false
 
 
new Vue({
    el:'#app',
    render: h => h(App),
    beforeCreate(){
        Vue.prototype.$bus = this//安装全局事件总线
    }
})

school.vue


 

 

student.vue


 

 

15.2props

这种通信方式适用与父向子传递数据

//父组件



这样我们的子组件就能拿到父组件传递过来的数据,并把它渲染上页面:

// 子组件




16.created和mounted区别

created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。

mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。

17.一个事件绑定多个方法

v-on ===>@click

给一个事件绑定多个方法

18.Vuex

vuex详解

具体代码怎么做看我vue2项目中的vuex

自己开发中遇到的问题_第3张图片

几句重要的核心:

  • mutations中定义的函数才有资格修改state中的数据
  • commit触发mutations的函数,dispatch触发actions的函数

Vuex是实现组件全局状态的一种机制,可以实现组件之间的数据共享

组件之间共享的数据才有必要存到vuex中

  • State
    • State是提供唯一公共的数据源,所有共享数据都需要统一放到Store的State中进行存储
//创建store数据源,提供唯一公共数据
const store =new Vuex.Store({
    state:{count:0}
})
    • 组件访问State中数据的第一种方式:【这种简单的用的多】
this.$store.state.全局数据名称 //想访问谁,就把谁的名称.出来,this可以省略
  • Mutation 【commit的作用就是调用某个mutation函数
    只有mutations中定义的函数才有资格修改state中的数据
    • Mutation用于变更Store中的数据,不可以直接操作Store中的数据
//在store.js中定义Mutation
const store =new Vuex.Store({
    state:{
        count:0
    },
    mutations:{
        add(state){
            //变更状态
            state.count++
        }
    }
})
//在components组件中触发mutations
methods:{
    handle1(){
        //触发mutations的第一种方式
        this.$store.commit('add')
    }
}
    • 可以在触发mutations时传递参数
//在store.js中定义Mutation
const store =new Vuex.Store({
    state:{
        count:0
    },
    mutations:{
        addN(state,step){
            //变更状态
            state.count+=step
        }
    }
})
//在components组件中触发mutations
methods:{
    handle2(){
       //在调用commit函数,
        //触发mutations时携带参数
        this.$store.commit('addN',3)
    }
}
  • Action
    Action用于处理异步任务
    如果想通过异步操作更改数据,必须通过Action,而不能使用Mutation,但是在Action中还是要通过触发Mutation的方式间接改变数据

//在store.js中定义Action
const store =new Vuex.Store({
    state:{
        count:0
    },
    mutations:{
        add(state){
            //变更状态
            state.count++
        }
    },
    actions:{
        addAsync(context){
            setTimeout(()=>{
                //通过commit触发mutations中的函数,实线异步操作
	 //在actions中,不能直接修改state中的数据,必须通过context.commit()触发某个mutation才行
                context.commit('add')
            },1000)
        }
    }
})

//在components组件中触发Actions
methods:{
    handle(){
        //触发actions的第一种方式
        //dispatch的作用就是触发某个对应的actions中的函数
        this.$store.dispatch('addAsync')
    }
}

总结:commit触发mutations的函数,dispatch触发actions的函数

  • 触发actions异步任务时携带参数

//在store.js中定义Action
const store =new Vuex.Store({
    state:{
        count:0
    },
    mutations:{
        add(state){
            //变更状态
            state.count++
        }
    },
    actions:{
        addAsync(context,step){
            setTimeout(()=>{
                //通过commit触发mutations中的函数,实线异步操作
	 //在actions中,不能直接修改state中的数据,必须通过context.commit()触发某个mutation才行
                context.commit('add',step)
            },1000)
        }
    }
})

//在components组件中触发Actions
methods:{
    handle(){
        //触发actions的第一种方式
        //dispatch的作用就是触发某个对应的actions中的函数
        this.$store.dispatch('addAsync',5)
    }
}

  • Getter

Getter用于对store中的数据进行加工形成新的数据,相当于计算属性的作用

//定义Getter
const store =new Vuex.Store({
    state:{
        count:0
    },
    getters:{
        showNum:state=>{
            return '当前最新的数值是【‘+ state.count+’】'
        }
    }
})

使用getters的第一种方式

this.$store.getters.名称

19.el-input宽度的设置

给el-input外部包裹一层el-col,来控制el-input的宽度

 
  	  
        
          
        
      
 

20.搜索框动态提示

21.Storage

localStorage:本地存储,提供的是一种永久性的本地存储,在关闭掉网页重新打开时,存储的内容依然保留;

localStorage.setItem('name',yjm)

sessionStorage:会话存储,提供的是本次会话的存储,在关闭掉会话时,存储的内容会被清除;

sessionStorage.setItem('name',yjm)
  • 关闭网页,localStorage的存储保持,sessionStorage的存储消失
  • 在页面之间实现跳转,localStorage和sessionStorage都会被保留,但在页面跳转中存储数据,推荐使用sessionStorage
  • 在页面外实现跳转(打开新的网页),localStorage会保留,sessionStorage不会被保留

22.路由重定向与懒加载

路由首页重定向

const routes =[
    //当路由路径后面没有跟后缀组件时,重定向到home组件进行展示,当有后缀home也会重定向到home
    {path:'/',redirect:'/home'},
    		//配置路由懒加载,按需去加载路由对应的资源,提高首屏加载速度
    {path:'/home',component:()=>import('../views/Home.vue')},
    {path:'/about',component:()=>import('../views/About.vue')}
]

23.css样式重置(normalize.css)

注意:最好使用normalize.css,别使用reset.scss(太暴力)

在每个项目的开发都需要进行项目css初始化

  • 对依赖进行安装
npm install --save normalize.css
  • 在main.js进行引入
import "normalize.css"

24.插槽Slot

当某个人需要使用这个组件的时候,但同时不希望组建的内容写死,则使用插槽自定义组件内容

24.1插槽基本使用

父组件中:
        
           
html结构1
子组件中:

24.2具名插槽

父组件中:
        
            

            
        
子组件中:
        

需要template和v-slot

具名插槽顾名思义就是给插槽起一个名字, 元素有一个特殊的属性:name

自己开发中遇到的问题_第4张图片

25.关于keep-alive的使用[唱歌系统]

Vue2

keep-alive的详解【按住ctrl再点击就可以打开网址】

作用: 在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性。

1.使用

// router.js
{
  path: '/home',
  name: 'home',
  component: () => import('../views/home.vue')
},
{ 
  path: '/test',
  name: 'test',
  component: () => import('../views/test.vue')
},
// App.vue

   

此外,我们还可以通过路由中的 meta 属性来控制,是否需要缓存。

将 test 路由中的 meta 添加 keepAlive 属性为 true,表示当前路由组件要进行缓存。

// router.js
{
  path: '/home',
  name: 'home',
  component: () => import('../views/home.vue')
},
{ 
  path: '/test',
  name: 'test',
  meta:{
    keepAlive:true
  },
  component: () => import('../views/test.vue')
},

keep-alive 代码可以结合 v-if 进行包裹,如果 meta 中的 keepAlive 为 true 进行缓存,否侧不进行缓存。


  

2.生命周期函数

activated:在组件被激活时调用,在组件第一次渲染时也会被调用,之后每次keep-alive激活时被调用。

deactivated:在组件被停用时调用。

Vue3

在后台管理系统中,点击侧边栏切换main区域的组件内容,给main组件的template区域添加


      
        
      

自己开发中遇到的问题_第5张图片

上图就实现了组件的缓存

*关于输入框的事件监听

el-input

@input=“usernameInput()” 监听输入事件
@keyup.native=“userNameKeyup($event)” 监听键盘事件
@paste.native=“usernamePaste” 监听粘贴事件
@blur=“blurUsername()” 监听失去焦点事件

input

代码示例

巨重要:!!!【歌唱管理员端的根据名字搜索学校的代码】



26.编程式路由导航的传参与接收

Vue中this.$router.push(参数) 实现页面跳转的详解

这是params的,query类似

传递:this.$router.push({
	name:'跳转页面的name',
    params:{
      //你需要通过页面跳转传递的参数  
    }
	})
接收:this.$route.params

27.多次执行相同push报错问题

自己开发中遇到的问题_第6张图片

解决方法:在router中的index.js重写该方法即可

//1、先把VueRouter原型对象的push,保存一份
let originPush = VueRouter.prototype.push;
//2、重写push|replace
//第一个参数:告诉原来的push,跳转的目标位置和传递了哪些参数
VueRouter.prototype.push = function (location,resolve,reject){
    if(resolve && reject){
        originPush.call(this,location,resolve,reject)
    }else{
        originPush.call(this,location,() => {},() => {})
    }
}

28.节流与防抖

vue2和3都使用lodash节流防抖:

vue3使用防抖和节流

防抖:用户操作很频繁,但是只执行一次,减少业务负担。

节流:用户操作很频繁,但是把频繁的操作变为少量的操作,使浏览器有充分时间解析代码

// 安装lodash
npm i --save lodash
// 节流


// 防抖


29.图片懒加载

图片懒加载

npm安装

npm i vue-lazyload -S

使用

  • main.js中使用
import Vue from 'vue'
import App from './App.vue'
import VueLazyload from 'vue-lazyload'

//注册插件
Vue.use(VueLazyload)

Vue.use(VueLazyload, {
  loading: 这里写的是懒加载的预览图【还没有加载出正真的图片的预览图】,
})
  • 在入口文件添加后,在组件任何地方都可以直接使用把 img 里的:src -> v-lazy
 
  变为了:
 

移动端

30.关于vant组件的注意点

定制自己的样式或主题

修改第三方UI组件库样式的四种方法

例如:

我想要修改tabbar的字体图标的大小

收藏 订单 消息

总结:找到想要修改的类,对其css样式进行重写,在引用第三方库的时候,需要使用:deep进行样式穿透

隐藏TabBar

coderwhy前端day64-第1128集

  • 在一个新的网页中,使用以下css



  • 首先在每个路由配置下面进行配置
//路由配置
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
 //映射关系
  routes: [
    {
      path:"/",
      redirect:"/home"
    },
    {
      path:"/home",
      component:()=>import("@/views/home/home.vue")
    },
    {
      path:"/city",
      component:()=>import("@/views/city/city.vue"),
    meta: {
      showTab: false
    }
    },
   
  ]
})

export default router

上面代码的意思就是如果底部需要tabbar就设置meta:{showTab:true}不需要的就设置meta:{showTab:false}

然后在app.vue中的tabbar组件(就是底部配置的router-link)中判断就行了这里的tabbar组件就是下面的底部导航

这里呢是给出v-if就是判断showTab是否为true了,为true显示tabBar为false不显示

31.点击TabBar标签获取索引值

  • 给van-tabs绑定事件


32.顶部导航栏和搜索框固定【p1133】

自己开发中遇到的问题_第7张图片



33.页面滚动的监听

const isShow=ref(false)
// 页面滚动
window.addEventListener("scroll",()=>{
const scrollTop=document.documentElement.scrollTop//已经滚动的高度
const scrollHeight =document.documentElement.scrollHeight//可滚动的总高度
const clientHeight =document.documentElement.clientHeight//可视区域的高度
console.log(scrollTop,scrollHeight,clientHeight);
if(scrollTop>0.85*clientHeight){
  isShow.value=true
}else{
  isShow.value=false
}
})

自己开发中遇到的问题_第8张图片

34.通过百度地图开放文档获取位置

视频教学:百度网盘 - 视频播放 (baidu.com)

操作文档:jspopularGL | 百度地图API SDK

自己开发中遇到的问题_第9张图片

35.移动端适配

百度网盘 - 视频播放 (baidu.com)

GitHub - evrone/postcss-px-to-viewport: A plugin for PostCSS that generates viewport units (vw, vh, vmin, vmax) from pixel units. The best choice to create a scalable interface on different displays by one design size.

将全局的px转换为vw

module.exports = {
  plugins: {
    'postcss-px-to-viewport': {
				//移动端适配,视口宽度375
     viewportWidth:375
    }
  }
}

36.沾满全屏的配置

在App.vue中配置以下代码

37.Vue3进行路由跳转

vue3.0 router路由跳转传参(router.push)_vue3 router.push 传参数_吃鱼吐泡泡的博客-CSDN博客

1.首先在需要跳转的页面引入API---useRouter

import { useRouter } from 'vue-router'

2.在跳转页面定义router变量

//首先在setup中定义
 const router = useRouter()

3.用router.push跳转页面

// 字符串
router.push('home')
 
// 对象
router.push({ path: 'home' })
 
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
 
// 带查询参数,变成 /register?userId=123
router.push({ path: 'register', query: { userId: '123' }})

38.解决存储对象显示[object object]的解决方法

VUE使用sessionStorage存取对象时会显示[object object]的解决方法_vue [object object]_Leon_BUAA的博客-CSDN博客

39.关于elementplus自动导入的方法

coderwhy day105 233

elementplus按需自动导入

  • 安装插件

npm install -D unplugin-vue-components unplugin-auto-import

  • 在vite.config.ts和vue.config.js中配置环境(就不需要在main.ts中进行引入了,安装插件之后直接使用)

Vite

// vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  // ...
  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})

Webpack

// vue.config.js
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

module.exports = {
  // ...
  plugins: [
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
}
  • 还需要观察tsconfig.json里面的include有没有将其加入编译范围[auto-imports.d.ts和components.d.ts需要自己手动添加进去]

注意:elementplus的反馈组件Feedback需要自己在页面js中手动导入

自己开发中遇到的问题_第10张图片

40.自定义elementPlus样式

  • 首先找到需要修改组件的标签名:

自己开发中遇到的问题_第11张图片

  • 局部样式改写 :deep( )
:deep(.el-input__inner){
 height: 100px;
}

在vue3项目中使用icon图标

icon图标的全局使用

// main.ts

import * as ElementPlusIconsVue from '@element-plus/icons-vue'

const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

41.后台管理系统侧边栏折叠

day106的262

Collapse 折叠面板

核心:

组件间存在父子关系,所以需要使用emit将子组件的事件传递到父组件中去

调整aside的宽度:

三元运算符

调整menu的宽度:

42.动态路由[后台管理系统难点]

coderwhy day107--270

动态路由:根据用户的权限,动态添加路由信息(而不是一次性注册所有的路由)

基于菜单(menus)的动态路由管理

  • 创建所有路由实例

在store中定义动态路由数组

const localRoutes:any[]=[
   {
          path: '/main/analysis/dashboard',
          component: () => import('@/views/main/analysis/dashboard/dashboard.vue')
        },
  ......
]
  • 接收后端返回的角色菜单先遍历再查找,在角色菜单中会返回对应的路由,将后端返回的路由与所有路由实例localRoutes进行对比,有相同的就通过addRoute添加到main当中
const route = localRoutes.find((item) => {
              return item.path === submenu.url
            })
// if(route)代表上面通过find已经查询出了相等的数据返回给了route
// 需要在全局router中给main组件命名为main才能添加进来
  if (route) router.addRoute('main', route)

自己开发中遇到的问题_第12张图片

main.ts

做了以上操作后,需要在main.ts中再次调用这个方法,否则当进入这个页面后会导致路径出错(需要在app.use(router之前))

自己开发中遇到的问题_第13张图片

43.JS数组对象互转

  • 对象转数组:Object.values(obj)
示例:
var obj = { name: '小明', age: 22 };
console.log( Object.values(obj) );  // ['小明', 22]
  • 数组转对象:展开运算符...
 const arr = ['小明', 22];
const obj = {...arr};       
console.log(obj);   //{0: '小明', 1: 22}

44.Http相应状态码[常见]

  • 200 客户端请求成功
  • 400 客服端的错误,服务器无法或者不进行处理
  • 401 未授权的错误,必须携带身份信息token或cookie
  • 403 客服端没有访问权限,被拒绝
  • 404 服务器找不到请求的资源
  • 500 服务器遇到了不知道处理的情况
  • 503 服务器不可用,暂时无法访问

45.dayjs对于时间的处理

  • 安装dayjs
npm install dayjs --save
  • 自己封装一个建议的函数(在util中定义一个date.js的函数)
import dayjs from 'dayjs'
export default function time (day){
   const finalTime =  dayjs(day).format('YYYY-MM-DD');
   return finalTime
}
  • 在需要使用的地方引入
import time from './utils/time'
console.log(time(1690033589685));//2023-07-22
console.log(time('2023-07-23T00:49:11.000Z'));//2023-07-23

46.在项目中使用animate-css

官网:Animate.css | A cross-browser library of CSS animations.

  • 首先安装animate.css
npm install animate.css --save
  • 安装了之后需要在main.ts中配置
import animated from 'animate.css'
const app = createApp(App)
app.use(animated)

情况一:进入页面自动展示动画

直接添加transition标签再使用class添加动画样式就能展示对应的动画

切记:再使用动画效果之前,一定要使用animate__animated


     

后台管理系统

情况二:触发事件造成dom元素切换时的动画

 
    
hello world
const show=ref(true) function handleClick(){ show.value=!show.value }

47.在项目中使用Lodash

  • 首先安装lodash
npm i --save lodash
  • 在页面中引入并直接使用即可
import _ from 'lodash'
  • 一些常见方法
//生成随机数
console.log(_.random(5))//生成0-5随机数
console.log(_.random(5,10))//生成5-10的随机数
// 数组去重
const arr=['red','yellow','blue','red']
console.log(_.uniq(arr))// ['red', 'yellow', 'blue']
//防抖函数
直接看28

48.el-select可输入选择


            

            
            
          
 selectBlur(e){
        this.$set(this.value, 'account', e.target.value)
    },

49.数字递增动画的实现

npm i countup.js

day 110 328

50.axios二次封装

个人建议去听尚硅谷硅谷甄选项目P28

import axios from 'axios'
// 第一步:利用axios对象的create方法,去创建axios实例(其他的配置:基础路径,超时时间)
let request=axios.create({
  // 基础路径
  baseURL:http://xxxxxxx,
  timeout:5000
})
// 第二步:request实例添加请求响应拦截器
request.interceptors.request.use((config)=>{
  // config配置对象,headers属性请求头,经常给服务器携带公共参数
  // 返回配置对象
  return config
})
// 第三步:响应拦截器
request.interceptors.response.use((response)=>{
  // 成功的回调
  // 可以简化数据
},(error)=>{
  // 失败的回调:处理http网络错误
})

// 对外暴露
export default request

51.Vue.prototype全局使用

我们可能会在很多组件里用到数据/实用工具,但是不想污染全局作用域。这种情况下,可以通过在原型上定义它们使其在每个 Vue 的实例中可用。

每个组件都是一个vue实例,Vue.prototype加一个变量,只是给每个组件加了一个属性,这个属性的值并不具有全局性。

52.vue中使用弹幕(vue-danmaku)

  • 安装
npm install vue-danmaku --save
  • 使用,全局注册



53.vue中的 v-bind传值的说明

            	//当传入的是:age="18",age这个属性传递的就是双引号里面的内容