Vue2知识

1.keep-alive

在使用keep-alive包裹动态组件时,会缓存不活跃的组件实例 ,在生命周期中会新增两个钩子函数activated和deactivated

activated触发时机:keep-alive组件激活时使用,在生命周期创建后(created)和挂载后(mounted)被调用(钩子触发顺序created->mounted->activated,当我们运用了组件缓存时,如果想每次切换都发送一次请求的话,需要把请求写在activated中,而写在created或mounted中只会在首次加载该组件的时候起作用) deactivated触发时机:keep-alive组件停用时调用

使用include和exclude时,组件要写name属性 export default{name:"domeName",......},还有一个参数max(最多缓存几个)

原理:在电脑内存中创建一个代码片段,把包含的组件筛进内存里面,切过去再切回来时从内存中把存进去的代码取出来渲染,而不用再去从服务器读取,效率快

2.mvvm

mvvm是一种架构模式(设计模式)m是model数据模型,v是view视图,vm是ViewModel视图模型,vm对m的数据有绑定挟持机制对v中有监听机制,使用Object.defineProperty递归挟持Vue实例对象data中的所有数据,对所有数据的访问就getter和setter代理了,当我们改变数据,就会触发setter函数,Vue的底层就会通知视图更新渲染 只要m中数据变化,就会通知视图更新渲染,只要视图有用户有输入,就会同步到m中;

m相当于vue中的data,v相当于template,vm相当于Vue实例对象(export default{})

观察者模式:设计模式 【了解】

初始化代码的时候,Vue的底层有一个observe 把所有数据都挟持了, 有一个订阅者Dep 和一个观察者Watcher ,Dep实现把访问过的属性收集起来了,当数据改变,触发setter,Dep通知观察者,说数据变化了,观察者调用更新方法,进行数据的更新,通知视图进行渲染。

js 复制代码
<div id="app"></div>
<script>
    //m
    let data={msg:"消息"}
    //v
function renderFn(){
    app.innerHTML=`<input oninput="handleIpt(this)" value="${data.msg}"><span>${data.msg}</span>`
}
renderFn()
let _msg=data.msg
    //vm Object.defineProperty
Object.defineProperty(data,"msg",{
    get(){return _msg},
    set(newVal){
        _msg=newVal
        watch()
    }
})
function watch(){
 renderFn()   
}
//视图有输入更新同步到m中
function handleIpt(e){
    data.msg=e.value
}
    </script>

//Vue3的底层实现:底层使用ES6新增的代理对象proxy
const o=new Proxy(data,{
    get(target,property){
        return target[property]
    }
    set(target,property,newVal){
    target[property]=newVal
}
})
function watch(){
    renderFn()
}
function handleInput(input){
    data.msg=input.value
}

3.自定义v-model

js 复制代码
//名为 value 的 prop 和名为 input 的输入事件
//<input v-bind:value="val" v-on:input="val = $event.target.value" />
<template>
    <son :value="val" @input="val=$event"></son>
<span>{{val}}</span>
</template>
<script>
    import Son from "./son.vue"
   erport default{
    data(){
        return{
           val:"父的默认值" 
        }
    },
    components:{
        Son
    },
    } 
</script>
//-------------子组件--------------
<template>
  <input :value="value" @input="handelIpt" />
</template>
<script>
    
   erport default{
    data(){
        return{
            
        }
    },
       props:{
           value:{
               type:String
               required:false
               default:"不传默认值就是我"
           } 
        },
            methods:{
                handelIpt(e){
                  this.$emit("input",e.target.value) 
                }
            }
    } 
</script>

4.data为什么是一个函数?

一个组件的data选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝 。如果data是一个对象,多个组件(实例对象)就会共享这份数据,组件data之间指向了同一内存地址 ,造成一个变了全都会变的结果。当data是一个函数时,组件实例化时会调用这个函数,返回一个新的对象,分配一个新的内存地址 ,地址不一样,数据就不会互相干扰,保证了组件的独立性和可复用性

5.计算属性computed和侦听器watch

computed主要用于逻辑计算,返回唯一结果,有依赖缓存 ,依赖的数据发生变化才会重新计算。使用的函数名就是函数返回的结果。(购物车)watch主要用于观察数据的变化,执行关联操作(面包屑,搜索栏);methods是方法,一般用于事件绑定的处理函数和函数调用,函数调用某些场景不一定需要返回值。

Vue源码:执行加载顺序Props-->Methods-->Data-->Computed-->Watch

js 复制代码
export default{
    data(){
        return{
            
        }
    },
    computed:{
      函数名(){
          return 结果
      } 
        //第一种
        name() {
    return this.firstName + ' ' + this.lastName
}
//第二种
name: {
  get() {
    return this.firstName + " " + this.lastName;
  },
  set(newVal) {
    let t = newVal.split(' ')
    this.firstName = t[0]
    this.lastName = t[1]
  },
}
    },
    watch:{
        //第一种
      "观察的数据"(newVal,oldVal){
       console.log(newVal,oldVal) //执行的操作
      },
        //第二种
        "isCheeckName":{
            //处理的函数,只要观察到isCheeckName变化,就会触发hander函数
            hander(newVal,oldVal){
              console.log(newVal,oldVal) //执行的操作  
            },
            deep:true,//开启深度观察
            immediate:true//该回调将会在侦听开始之后被立即调用一次
        }
       
    },
    methods:{
        //调用需要(),不一定有返回值,没有依赖缓存,每次调用,就会重新执行里面的所有代码
    },
}

6.# this.$nextTick,this.set

js 复制代码
//在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
//created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中
this.$nextTick(() => {
   // 更新数据 dom更新渲染完成 就会触发
   console.log(document.querySelectorAll('li')) 
})
//Vue初始化的时候,只会挟持data中的数据, 不会挟制数组, 所以,如果给对象添加新数据或修改数据的数据, 都不会触发视图更新,使用Vue.set可以重新挟持数据,让数据具备响应式。
this.$set(对象, 属性名, 新的值)
this.hobs.splice(1, 1, 'Vue')
this.$set(this.hobs, 1, 'React')

7.实例属性

js 复制代码
//$refs,$parent,$children,$attrs,$listeners,$el
<template>
    <div ref='box'></div>
</template>
mounted(){
    this.$refs.box//<div data-v-048022ad></div>//获取DOM
}
methods:{
    //$parent 既 可 以 接 受 父 组 件 数 据 , 又 可 以 修 改 父 组 件 数 据, 是 双 向 的
//$parent 可以调用父组件的方法
    //想在子组件里获取父组件的元素之类的,必须使用nextTick
    parentPrint(){
      this.$nextTick(() => {
            this.$parent.fn()
          }) 
        this.$parent.data='操作父组件的属性'
    }
}
$children 当前实例的直接子组件
$attrs 拿绑定到子组件标签上的属性(排除: props接收的 ,class、style)
$listener 拿绑定到子组件标签上的事件(排除: .native)
$el 提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标
$root 获取根组件的实例对象
provide选项应该是一个对象或返回一个对象的函数, 可以提供数据。
inject选项,可以把祖辈组件,提供的数据,注入进入当前组件。

8.插槽v-slot

分为匿名插槽,具名插槽,自定义插槽

js 复制代码
//插槽主要在子组件预留位置,父组件把内容插入,实际的用途主要用于组件的封装,内容可以自定义
//匿名插槽
<div>
    <span>非插槽内容</span>
    <slot>我是匿名插槽默认值</slot>
    <slot name="conName">我是具名插槽默认值,想插进来必须带上名字</slot>
</div>
//------作用域插槽,可以写名字也可以不写名字
<template>
    <slot :title="title" msg="小貂禅">我是作用域插槽默认值</slot>
</template>
title="作用域"
js 复制代码
<model>
    <p>沃斯插入插槽的内容</p>
    <span slot="conName">我是插入具名插槽的内容<span>
</model>
   //----------作用域插槽
   <model slot-scope="scope">
       <p>{{scope.title}}</p>
       <p>{{scope.msg}}</p>
       <i>我是作用域插槽插进去的东西</i>
</model>     
import Model from "@/components/model/Model.vue"

9.minin混入

如果有相同选项,用自己的;抽取公共配置项,自由简单,容易混乱,难以维护

js 复制代码
//定义一个混入对象
export const myMixin={
    data(){
        return{
            msg:"唱跳"
        }
    },
    created(){
        this.hello()
    },
    methods:{
        hello(){
            console.log("沃斯混入进来的")
        }
    }
}
js 复制代码
import { myMixin } from "@/mixin/index.js"
export default{
mixins:[myMixin]//混入
}

10.动态组件component :is

Vue 动态组件component

js 复制代码
//场景:局部选项卡切换,多个组件使用同一个挂载点并且动态切换
//<component :is="你具体要显示那个组件的变量"> </component>
<template>
  <div>
      Home页面
      <button @click="fun('One')">点我去one</button>
      <button @click="fun('Two')">点我去two</button>
      <button @click="fun('Three')">点我去three</button>
      <component :is="com"></component>
  </div>
</template>
 
<script>
import One from "@/components/one.vue"
import Two from "@/components/two.vue"
import Three from "@/components/three.vue"
export default {
    data(){
        return {
            com:"Three"
        }
    },
     methods:{
        fun(data){
            this.com = data
        }
    },
    components:{
        One,Two,Three
    }
}
</script>
//可以配合keep-alive使用

11.异步组件

异步组件

js 复制代码
components:{
//异步组件
'jl-button':()=>import("@/components/jlButton.vue")
}

12.内置组件

  • keep-alive
  • slot
  • component
  • transition 动画
js 复制代码
 <!-- 内置的动画组件 把我们要做动画的组件包裹起来 -->
    <transition name="fade">
      <jl-model @close="visible=false" v-show="visible"></jl-model>
    </transition>

// 进入动画的过程 和 离开动画的过程
.fade-enter-active, .fade-leave-active {
  // 过渡
  // transition: opacity 5s;
  transition: all 0.3s;
}

// 进入的瞬间 离开的瞬间
.fade-enter, .fade-leave-to  {
  // opacity: 0;
  transform: translateX(-100%);
}

13. 递归组件

组件内部,自己使用自己,就是递归组件,常见的就是: 菜单树, 注意:组件要给name,才可以。 组件给name的作用:

  • 递归组件,可以自己在模板中使用自己
  • keep-alive缓存组件

14.全局组件Vue.component

js 复制代码
//创建一个filters文件夹下面的index.js
//首字母大写
export function firstUpperCase(value){
    return value.slice(0,1).toUpperCase()+value.slice(1)
}
//千分位逗号隔开
export function thousand(value){
    return value.replace(/(?=(\B)(\d{3})+$)/g,",")
}
//main.js
//第一种 高阶
//引入过滤器函数们
import * as filters from "@/filters"
//循环
Object.keys(filters).forEach(key=>{
    //自动注册为全局过滤器
    Vue.filter(key,filters[key])
})
//第二种 
Vue.filter("fixed2",(value)=>{return value.toFixed(2)})
//组件中使用
<template>
<p>{{666|fixed2}}</p>
<p>{{"hello"|firstUpperCase}}</p>
<p>{{"54088"|thousand}}</p>
</template>

15.全局自定义指令directive

js 复制代码
//main.js
Vue.direactive("ellipsis",{
    //当被绑定的元素插入到DOM中时
    inserted(el,expr){
        el.style.width=expr.value+"px"
        el.style.overflow="hidden"
        el.style.whiteSpace="nowrap"
        el.style.textOverflow="ellipsis"
    }
})
//第二种高阶写法跟全局过滤器基本一致
<template>
<p v-ellipsis="99">沃斯敲键盘两年半的cv工程师</p>
</template>
//管理系统按钮级的权限高级写法就可以用全局自定义指令,简单就用v-if也可以
相关推荐
看到请催我学习19 分钟前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript
golitter.2 小时前
Vue组件库Element-ui
前端·vue.js·ui
道爷我悟了2 小时前
Vue入门-指令学习-v-on
javascript·vue.js·学习
.生产的驴3 小时前
Electron Vue框架环境搭建 Vue3环境搭建
java·前端·vue.js·spring boot·后端·electron·ecmascript
老齐谈电商3 小时前
Electron桌面应用打包现有的vue项目
javascript·vue.js·electron
LIURUOYU4213083 小时前
vue.js组建开发
vue.js
九圣残炎4 小时前
【Vue】vue-admin-template项目搭建
前端·vue.js·arcgis
《源码好优多》4 小时前
基于SpringBoot+Vue+Uniapp的植物园管理小程序系统(2024最新,源码+文档+远程部署+讲解视频等)
vue.js·spring boot·uni-app
计算机学姐4 小时前
基于微信小程序的调查问卷管理系统
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis
黄尚圈圈8 小时前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts