当前位置:   article > 正文

Vue随笔摘录_this.intervalid = setinterval(() => { this.toquery

this.intervalid = setinterval(() => { this.toquery() }, 5000);
1.setTimeout/setInterval
  • a. 无法正确使用this指向
  //箭头函数访问this实例因为箭头函数本身没有绑定this
  setTimeout(() => {
    console. log(this);},  500) ;
    //使用变量访问this实例let self=this;
  },1000);
  • 1
  • 2
  • 3
  • 4
  • 5
  • b. setInterval路由跳转继续运行并没有销毁

比如一些弹幕,走马灯文字,这类需要定时调用的,路由跳转之后,因为组件已经销毁了,但是setlnterval还没有销毁,还在继续后台调用,控制台会不断报错,如果运算量大的话,无法及时清除,会导致严重的页面卡顿。

  created() {
       this.intervalid = setInterval(() => {
          this.layerError = "";
          this.Timer = null;
      }, 100000);
   }
  beforeDestroy( ){
    //我通常是把setInterval( )定时器赋值给this实例,然后就可以像下面这么暂停。
    clearInterval(this.intervalid);
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
2.Vue路由拦截浏览器后退实现草稿保存类似需求

为了防止用户突然离开,没有保存已输入的信息。

  //在路由组件中:mounted(){},
  beforeRouteLeave (to, from, next) {
      if(用户已经输入信息){
        //出现弹窗提醒保存草稿,或者自动后台为其保存
      }else{
        next(true);//用户离开
      }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
3.自定义组件添加click等事件不生效
//使用.native修饰符
  <template>
    <el-progress type="circle" :percentage=0" @click.native=“stopProgress”></el-progress>
  </template>
  <script>
    export default {
        methods:{
            stopProgress() { 
            console.log('停止')
            }
        }
    }
  </script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
4.手动操控自定义组件

一些自定义组件,需要去获取组件对象进行一些其他的Dom操作 mounted

  <template>
    <el-progress type="circle" :percentage="O" ref="progress"></el-progress></template>
  <script>
    this.$refs.progress //组件对象实例, 可以手动调用组件的内置方法和属性
    this.$refs.progress.$el //组件 对象的最外层dom元素
  </script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
5.深度作用选择器

scoped的样式,希望影响到子组件的默认样式

  <style scoped>
    .a >>> .b { /* ... */ }
  </style>
    //有些像Sass之类的预处理器无法正确解析>>>。这种情况下你可以使用/deep/操作符取而代之- - - -这是一个>>>的别名,同样可以正常工作。  <style scoped lang=“scss”>
    .a /deep/ .b { /* ... */ }
  </style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
6.Vue数组/对象更新视图不更新

this. $set(你要改变的数组/对象,你要改变的位置/key,你要改成什么value)
数组原生方法触发视图更新( vue官网可查):
整体替换数组/对象

7.Vue Filters过滤器的使用
  <!-- 在双花括号中 -->
  <div>{{ message | DateFormat }}</div>    //展示正确时间
  <!--'v-bind'-->
  <div v-bind:id="rawId | formatId"></div>

  Demo:一个日期过滤器返回yyyy- MM-ddhh:mm:ss的样式
  引入一个提前写好日期格式化的js  import dayjs from ‘dayjs';
  export default {
     data() {
        return {
                //时间毫秒
                message:18324798324789 
            }
    },
    filters: {
          //传入进行日期格式化
      DateFormat(value) {
        return dayjs(value).format(YYYY-MM-DD HH:mm:ss")
          } 
    }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
8.Vue深度watch与watch立即触发回调

在watch里面监测对象里面对应的值是监测不到的,可以用如下方法。
选项: deep
在选项参数中指定deep:true,可以监听对象中子属性的变化。
选项: immediate
在选项参数中指定immediate:true,将立即以表达式的当前值触发回调,也就是默认触发一次。

  watch: {
    obj: {
        handler(val, oldVal) {
          console.log('属性变化触发这个回调',val, oldVal); 
        },
        deep: true // 监测这个对象中每一个属性的变化
    },
    step: { // 属性 //watch
       handler(val, oldVal) {
        console.log("默认触发一次", val, oldVal); 
       },
       immediate: true // 默认触发一次
    }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
9.v-if 和 v-show 区别

使用 v-if 的时候,如果值为 false ,那么页面将不会有这个 html 标签生成。
v-show 则是不管值为 true 还是 false , html 元素都会存在,只是 CSS 中的 display显示或隐藏。

10.生命周期
  • beforeCreated():在实例创建之间执行,数据未加载状态。
  • created():在实例创建、数据加载后,能初始化数据,DOM 渲染之前执行。
  • beforeMount():虚拟 DOM 已创建完成,在数据渲染前最后一次更改数据。
  • mounted():页面、数据渲染完成,真实 DOM 挂载完成。
  • beforeUpadate():重新渲染之前触发。
  • updated():数据已经更改完成,DOM 也重新 render 完成,更改数据会陷入死循环。
  • beforeDestory() 和 destoryed():前者是销毁前执行(实例仍然完全可用),后者则是销毁后执行。
11.解释单向数据流和双向数据绑定

单向数据流: 顾名思义,数据流是单向的。数据流动方向可以跟踪,流动单一,追查问题的时候可以更快捷。缺点就是写起来不太方便。要使 UI 发生变更就必须创建各种 action 来维护对应的 state。
双向数据绑定:数据之间是相通的,将数据变更的操作隐藏在框架内部。优点是在表单交互较多的场景下,会简化大量与业务无关的代码。缺点就是无法追踪局部状态的变化,增加了出错时 debug 的难度

12.Vue 的双向绑定数据的原理

vue 实现数据双向绑定主要是:采用数据劫持结合“发布者 - 订阅者”模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter、 getter,在数据变动时发布消息给订阅者,触发相应监听回调。

13.Vue 如何去除 URL 中的

vue-router 默认使用 hash 模式,所以在路由加载的时候,项目中的 URL 会自带 “#”。如果不想使用 “#”, 可以使用 vue-router 的另一种模式 history:

new Router
	({
 		 mode: 'history'
 		 routes: [ ]
	})
  • 1
  • 2
  • 3
  • 4
  • 5

需要注意的是,当我们启用 history 模式的时候,需要后台配合

14.$route 和 $router 的区别

$router 为 VueRouter 实例,想要导航到不同 URL,则使用 $router.push // replace方法。
$route 为当前 router 跳转对象里面可以获取 name 、 path 、 query 、 params 等。

15. NextTick 是做什么的

$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后l立即使用 $nextTick更新

16.Vue 组件 data 为什么必须是函数

因为 JS 本身的特性带来的,如果 data 是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性时,会影响到所有 Vue 实例的数据。如果将 data 作为一个函数返回一个对象,那么每一个实例的 data 属性都是独立的,不会相互影响了。

17.Vue 中 key 的作用

key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

18.对 keep-alive 的了解

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

<keep-alive>
	<component>
		<!-- 该组件将被缓存! -->
	</component>
</keep-alive>
  • 1
  • 2
  • 3
  • 4
  • 5
19.Vue 中怎么自定义指令
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function(el) {  
		// 聚焦元素
   		 el.focus()
  }
})

directives: {
  focus: {
    // 指令的定义
    inserted: function(el) {
      el.focus()
    }
  }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
20.组件通信
  • a.父组件向子组件通信
    • 子组件通过 props 属性,绑定父组件数据,实现双方通信。
  • b.子组件向父组件通信
    • 将父组件的事件在子组件中通过 $emit 触发。
  • c.非父子组件、兄弟组件之间的数据传递
/*新建一个Vue实例作为中央事件总嫌*/
let event = new Vue ();
/*监听事件*/
event.$on('eventName', (val) => {
    //......do something
    });

/*触发事件*/
event.$emit('eventName', 'this is a message.')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
21.router.push()与router.replace()

router.push()会在history栈中添加一个新的纪录,后退会返回之前的url;
单击< router-link :to=’’>等同于router.push()
router.replace()不会添加新纪录,而是自动替换当前的history

22.常用路由守卫

每个守卫方法接收三个参数:
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
确保要调用 next 方法,否则钩子就不会被 resolved。

1.全局守卫

  • a. 在所有的router访问的时候执行的操作之前调用
router.beforeEach((to, from, next) => {
  /* 路由发生变化修改页面title */
  if (to.meta.title) {
    document.title = to.meta.title
  }
  next()
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • b.需要默认登入状态,不能只写个链接就免登入
// 全局路由守卫
router.beforeEach((to, from, next) => {
  const nextRoute = ['User', 'Cart', 'GoodsDetail'] // 需要登录的页面
  let isLogin = localTake('userMsg')  // 判断是否登录,本地存储有用户数据则视为已经登录
  // 未登录状态;当路由到 nextRoute 指定页时,跳转至 UserLogIn
  if (nextRoute.indexOf(to.name) >= 0) { // 检测是否登录的页面
    if (!isLogin) { // 如果未登录(本地存储无用户数据),并且要跳到登录页面
      if (from.name === 'UserLogIn') {
        next('/')
        return
      }
    // 登录后,跳到到当前页面
      router.push({
        name: 'UserLogIn',
        params: {redirect: to.fullPath}  
      })
    }
  }
  // 已登录状态;当路由到 UserLogIn 时,跳转至 Home
  if (to.name === 'UserLogIn') {
    if (isLogin) {
      next('/')
      return
    }
  }
  next() // 必须使用 next ,执行效果依赖 next 方法的调用参数
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在这里插入图片描述

2,组件内 beforeRouteUpdate
/foo/:id /foo/1与 /foo/2不会更新路由

  // 路由复用,但参数改变触发
  beforeRouteUpdate (to, from, next) {
    console.log(to)
    this.loadImgById(to.params.id)
    next()
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
23.路由组件懒加载

代码分割

import Goods from ' pages/goods/goods.vue '

const Goods = () => import(' pages/goods/goods.vue ')
  • 1
  • 2
  • 3
24.图片懒加载
npm i -S vue-lazyload

import  VueLazyload from  'vue-lazyload'

Vue.use(VueLazyload,{     // 自定义一个指令
	preLoad:1.3,
	errer:'dist/error.png',
	loading:'dist/loading.gif',
	attempt:1
})
<img v-lazy = 'xxx'>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
25.时间过滤器
	npm i -S moment
	import moment from 'moment
	Vue.filter('data-format',function(value,formatStr='YYYY-MM-DD HH:mm:ss'){     // 默认值
		return moment(value).format(formatStr)
	})
  • 1
  • 2
  • 3
  • 4
  • 5
25.打包优化

a. vue脚手架提供了一个用于可视化分析打包文件的包,webpack-bundle-analyzer和配置
b. 启动打包可视化: npm run build --report

npm run build --report
  • 1

比如上面说的moment占用体积大,用 data-fns

npm i -S data-fns
import format from 'date-fns/format'
	Vue.filter('data-format',function(value,formatStr='YYYY-MM-DD HH:mm:ss'){     // 默认值
		return format(value).format(formatStr)
	})
  • 1
  • 2
  • 3
  • 4
  • 5
26.组件的通信
  • ref $parents 和 $children
// component-a
export default{
  data (){
   	return{
      title:'Vue.js'
   }
  },
  methods:{
    sayHello (){
      window.alert('Hello');
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
<template>
  <component-a	ref="comA"></component-a>
</template>
<script>
  export	default{
    mounted (){
      const comA =this.$refs.comA;
      console.log(comA.title); // Vue.js
      comA.sayHello();	// 弹窗
    }  
}
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

$parent 和 $children 类似,也是基于当前上下文访问父组件或全部子组件的。这两种方法的弊端是,无法在跨级或兄弟间通信。

  • provide / inject

一种无依赖的组件通信方法:Vue.js 内置的 provide / inject 接口。provide / inject 是 Vue.js 2.2.0 版本后新增的 API,在文档中这样介绍 :

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。

假设有两个组件: A.vue 和 B.vue,B 是 A 的子组件:

// A.vue
export	default	{
  provide:{name:'Aresn'}
}

// B.vue
export	default{
  inject:['name'],
  mounted (){
    console.log(this.name);// Aresn
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

需要注意的是: provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
只要一个组件使用了 provide 向下提供数据,那其下所有的子组件都可以通过 inject 来注入,不管中间隔了多少代,而且可以注入多个来自不同父级提供的数据。需要注意的是,一旦注入了某个数据,那这个组件中就不能再声明 这个数据了,因为它已经被父级占有。
provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

  • $attrs和 $listeners

如果父组件 A 下面有子组件 B,组件 B 下面有组件 C,这时如果组件 A 想传递数据给组件C怎么办呢? Vue 2.4 开始提供了 $attrs 和 $listeners 来解决这个问题,能够让组件 A 之间传递消息给组件 C。

Vue.component('C', 
		{
		template: `
            <div>
				<input type="text" v-model="$attrs.messagec" @input="passCData($attrs.messagec)"> 
			</div>`,
		methods: {
				passCData(val) {
					//触发父组件A中的事件
					this.$emit('getCData',val)
				}
			}
		})


Vue.component('B', {
			data() {
				return{
					mymessage: this.message
				}
			},
			template: `
            <div>
                <input type="text" v-model="mymessage" @input="passData(mymessage)"> 
                <!-- C组件中能直接触发getCData的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 -->
                <!-- 通过v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
                <C v-bind="$attrs" v-on="$listeners"></C>
            </div>`,
			props: ['message'],
			//得到父组件传递过来的数据
			methods: {
				passData(val) {
					//触发父组件中的事件
					this.$emit('getChildData',val)
				}
			}
		})

Vue.component('A', {
			template: `
            <div>
                <p>this is parent compoent!</p>
                <B :messagec="messagec" :message="message" v-on:getCData="getCData" v-on:getChildData="getChildData(message)"></B>
            </div>`,
			data() {
				return{
					message: 'hello',
					messagec: 'hello c'
					//传递给c组件的数据
				}
			},
			methods: {
				getChildData(val) {
					console.log('这是来自B组件的数据')
				},
				//执行C子组件触发的事件
				getCData(val) {
					console.log("这是来自C组件的数据:" +val)
				}
			}
		})

var	app = new Vue({
		el: '#app',
		template: `
            <div>
                <A></A>
            </div>
        `
	})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/633246
推荐阅读
相关标签
  

闽ICP备14008679号