vue学习笔记

vue学习笔记

2021-01-19

  • 传递本地路径的问题
    在父子组件通信中,子组件需要图片地址,父组件传递图片地址时,图片地址是本地图片,使用别名@以及相对路径…/都会导致图片路径出错.
    解决方法:使用require引入
<feature-view :imageUrl="featureImageUrl"></feature-view>

data() {
    return {
      featureImageUrl: require("@/assets/img/home/recommend_bg.jpg"),
    };

2021-01-25

  • 封装scroll组件
    设置scroll组件的margin-top,设置home div高为100vh,结果出现home的高为100vh+scroll的margin-top.原因是因为父元素的高度塌陷,scroll组件和home的顶部重合到了一起,scroll的margin-top成了home的margin-top导致高度不对, 以后多注意高度塌陷的问题!!!

2021-01-27

  • bus总线
    在封装scroll组件的时候,使用了better-scroll出现bs可滚动高度不对的问题。出现的问题在于bs对象初始化时,会计算出一个高度,等到异步图片加载完成高度会变高,但是bs对象没有调用refresh()方法,导致可滚动高度不对.
    由此学习到了bus方法总线机制.如果图片加载完成调用upload方法回调派发事件 ,需要多次派发事件才能到达home组件然后调用scroll组件的refresh()方法.由此 bus总线可以派发事件,而在任何一个组件进行监听.

  • Vue父子组件的加载顺序
    1: 父 beforeCreate
    2 父 created
    3 父 beforeMount
    4 子 beforeCreate
    5 子 created
    6 子 beforeMount
    7 子 mounted
    8 父 mounted

  • 防抖函数和节流函数

//	防抖函数  核心原理:有人调用就取消定时器,重新设置定时器过一会调用
function debounce(fn,delay){
    let timer = null;
    return function(...args){
      clearTimeout(timer);
      timer = setTimeout(()=>{
        fn.apply(this,...args);
      },delay)
    }
  }
//节流函数 核心:执行完一个函数后,设置一个定时器,定时器内函数不能执行
  function throttle(fn, delay) {
    let timer = null;
    return function (...args) {
      if (timer) return;
      fn.apply(this,args);
      timer = setTimeout(() => {
        timer = null;
      }, delay)
    }
  }

2021-01-28

  • 关于粘性布局的问题
    因为使用了better-scroll进行滚动管理,所以导致sticky布局无法正确获取滚动的距离,导致css原生的sticky布局会失效.
    于是想要使用js来控制.监听bs的滚动,滚动到某个距离时,把元素设置为fixed布局,但是又出现了两个问题,
    1: 把元素设置成为fixed会导致元素脱标,表现为元素的高度瞬间消失,下面的元素顶了上去,出现了元素的跳跃效果.
    2:设置成为fixed布局之后,需要设置top属性来确定位置,但是由于元素在bs管理所元素的内部,而bs所管理的元素是利用transform来实现滚动,这会导致top是根据bs所管理元素的最上方计算top,就会出现设置为fixed的元素消失,出现在距离滚动元素最上方top距离的位置.
    解决方法:设置一个与要设置为粘性布局一模一样的组件(属性/事件全部一样,调用的方法都是公用的),将新设置的组件放到滚动元素的外面并默认隐藏,并设置好粘性布局的样式. 当滚动到某个距离之时,将新设置的组件显示出来,就实现了看起来与粘性布局一模一样的样式.
  • 保留离开页面时的位置
    要实现离开页面再回来时显示的位置和原来是一致的,首先保证页面页面离开不会被销毁,所以在
    < router-view >加上<keep-allive>保证页面不被销毁.
    其次要离开的时候记录滚动位置,回来的时候在滚动到离开时的滚动位置. 使用两个钩子函数,
    activateddeactivated 注意:有一个小bug,active在对一次页面创建也会调用一次,这时其他组件都还没创建导致元素获取为null,注意下就可以.

2021-01-29

  • 封装类class
    在遇到发送请求获取数据的情形时,经常会出现这种情形: 从服务器返回的数据太过复杂和杂乱,将数据传递给子组件时单个属性传递太过繁琐,整体对象传过去无用信息太多,太过杂乱. 所以可以用es6的class机制,将需要传递的数据封装为一个类,实例化为类的对象进行传递,这样数据格式有用且不会出错.

2021-01-30

  • 一个bug
    在Detail.vue这个组件中,我们使用了GoodsListItem.vue这个组件,这个组件图片加载完成会通过事件总线派发事件,Detail.vue中监听到事件后,刷新better-scroll的高度,保证滑动不出现问题.但问题在于因为home组件设置keep-alive导致home组件并没有被销毁,而home组件还在监听事件总线的同样的时间,导致Detail.vue中图片加载完成,home的detail都会进行scroll的刷新
    解决方法:离开home组件时就不应该再监听事件总线的方法,在钩子函数deactived中取消事件监听.

2021-01-31

  • mixin
    学习到了mixin混入,mixin是一种技术,他可以把多个组件用到的公用的组件内容抽取到一个对象当中,并在用到的组件中引入,这样能降低代码的重复程度.例子如下:
    在下面的组件当中,将data和mounted的一部分抽取到了mixin当中,引入组件后,data和mounted中的内容会和原本组件中的data/mounted合并到一起,从而增加代码的复用程度,减少冗余.
import { debounce } from "@/common/utils.js";

export const goodsListItemUploadMixin = {
  data(){
    return {
      goodsListItemUploadHandler: null, //图片加载完成的回调事件
    }
  },
  mounted() {
    // 防抖
    let refresh = debounce(this.$refs.scroll.refresh, 500);
    // 事件总线
    this.goodsListItemUploadHandler = () => {
      // this.$refs.scroll.refresh();
      refresh();
    };
    this.$bus.$on("goodsListItemUpload", this.goodsListItemUploadHandler);
  }
}
  • 高度bug
    获取高度时会有各种各样的问题,都是因为dom加载,图片加载未完成所产生的的问题.mounted钩子中,因为数据是异步加载所以可能导致没有dom,高度不对. 使用nexttick可以保证dom渲染. 但是dom渲染完成后,如果有图片的话图片尚未加载完成,也会导致高度不对.

2021-02-01

  • vuex mutations原则
    vuex的mutations尽量一个方法只做一件事情,便于vue的插件进行追踪,比如今天的购物车添加商品,我在mutations的方法中做了两件事情,一是判断是否存在存在商品,二是设置数量添加进购物车. 这样最好将逻辑放入到action中进行,把上述的两个方法抽到mutations中形成两个单一操作.

2021-02-02

  • vuex可返回promise进行 异步操作
    做项目遇到一个需求,当点击添加进购物车时,将商品添加到购物车,添加进购物车后进行弹窗提示添加成功. 这个需求有两个点: 一是:修改vuex中的数据,需要使用vuex的actions. 二是: actions中添加到购物车的操作是一个 异步操作.
    所以不能调用添加进购物车的方法后直接进行弹窗,因为 异步操作需要时间.所以 使用异步操作返回promise来解决.

  • vuex的映射
    在vuex中,getters和mutations以及actions都是可以映射的.getters是计算属性,所以可以通过 …mapGetters映射到组件的computed计算属性中, mutations和actions都是方法,所以可以通过**…mapMutations和…mapActions映射到methods方法中.

  • 通过插件的方式来封装组件(important)

  1. 正常封装一个toast组件
  2. Vue.use(xxx)的时候会调用xxx的install方法 所以可以在install方法让Vue.prototype.$toast= Toast
//main.js中
import toast from '@/components/common/toast'
Vue.use(toast);
  1. 具体代码
let obj = {};
obj.install = function (Vue) {
  let toastConstructor = Vue.extend(Toast);
  //通过组件构造器新建一个组件对象
  let toast = new toastConstructor();
  //将组件对象挂载到一个dom元素上
  toast.$mount(document.createElement('div'));
  //t.$el就是div  将组件放到body中
  document.body.appendChild(toast.$el);

  Vue.prototype.$toast = toast;
}
export default obj;
  1. 然后就可以通过下面方式调用
this.$toast.show('123',2000);
  1. Toast组件代码
<template>
  <div class="toast" @click.prevent="hiddenToast" v-if="isShow">
    <div class="content">
      {{ message }}
    </div>
  </div>
</template>

<script>
export default {
  name: "Toast",
  data() {
    return {
      isShow: fasle,
      message: "",
    };
  },
  methods: {
    hiddenToast() {
      this.isShow = fasle;
    },
    show(message = "默认文字", duration = 2000) {
      this.isShow = ture;
      this.message = message;
      setTimeout(() => {
        this.isShow = fasle;
      }, duration);
    },
  },
};
</script>

2021-02-03

  • fastclick解决移动端300ms延迟问题
  • vue中图片的懒加载 使用vue-lazyload
  • 样式大小的调整,可以使用px2vwpx2rem自动将px转换单位,适配不同屏幕.

Vue响应式原理的两个核心点

  1. Object.defineProperty

     Vue第一个核心问题就是如何监听数据的变化. 在js中属性有get 和 set 两个方法.设置属性的值时
     会调用set方法,意思就是 更改属性的值是会调用属性的set方法. 而我们想要监听属性的变化,所以,
     所以我们在set中就可以监听到属性的变化,做一些事情.  这就实现了监听数据变化.
    
因为要监听Vue中每一个data的变化,所以new Vue()的时候要劫持每一个属性.设置getset
new Vue({
	el: 'app',
	data:{
		name: 'zhangsan',
		age: 18
	}
})
因为data中那个每一个属性都需要监听,每一个属性变化的时候都要做一些事,所以获取到data的每一个属性
let data = {};
Object.defineProperty(data,name,{
	get(){
		//做一些事情,获取数据会调用get,在这里做一些事情就监听到了获取数据
		return name;
	},
	set(value){
		//做一些事情,更改数据会调用set,在这里做一些事情就监听到了更改数据
		name = value;
	}
})
  1. 发布订阅者

     上面已经讲了第一个核心的问题,就是怎么监听到数据的变化.下一个核心问题就是,我怎么知道谁
     引用了data中的属性,也就是data变化时,我怎么知道谁要跟着变.这里使用了发辫订阅者模式.也就
     是说我每一个属性都建立一个Dep(Dependency,发布者)对象,发布者对象有一个订阅者属性,是一
     数组,每一个调用属性的人都是订阅者,因为属性变化了,调用者也要变,所以调用者都是订阅者,为
     订阅者建立一个Wacther对象.
    
Class Dep{
	constructer(){
		this.subscribe = []; //每个发布者都有订阅者
	},
	notify(){
		//当发布者发生变化的时候,调用notity方法,通知每一个订阅者,调用订阅者的update方法.
		this.subscribe.foreach(item => item.update()); 
	}
}
Class Watcher{ //订阅者
	constructer(){
		this.value = ''; //每个订阅者都有value
	},
	update(){
		//当发布者更新的时候,update就会被调用,在这里做一些事情
		更新视图(也就是view)
	}
}

图解

在这里插入图片描述

2021-04-08

  1. NProgress的使用
  2. 有关router路由添加原信息
    • 一个路由对应一个页面
    • 所以可以在router中添加meta原信息,代表路由页面的信息,比如页面的标题页面的权限
  3. 动态路由权限
    在一个系统中,总会涉及到用户的权限, 在前端根本的解决途径就是不给多余的路由, 也就是只给他可以访问的路由.
    所以可以采用动态路由表.

    采用router.addRoute api

示例: 动态路由表示例 https://blog.csdn.net/qq_42778001/article/details/105047242

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值