深海 深海
首页
  • 随手笔录
  • 电影
  • 音乐
  • 书籍
汇总
面试
  • 开发工具
  • VScode插件
  • Git
  • Mac时代
  • 前端工具
  • Chrome
  • HTML
  • CSS
  • Javascript
  • Typescript
  • Axios
  • 框架

    • Vue
    • uni-app
  • Nginx
  • Linuk
事例
关于

深海

人生如逆旅,我亦是行人
首页
  • 随手笔录
  • 电影
  • 音乐
  • 书籍
汇总
面试
  • 开发工具
  • VScode插件
  • Git
  • Mac时代
  • 前端工具
  • Chrome
  • HTML
  • CSS
  • Javascript
  • Typescript
  • Axios
  • 框架

    • Vue
    • uni-app
  • Nginx
  • Linuk
事例
关于
  • HTML
  • CSS的奥秘

  • JavaScript

  • TypeScript

  • Vue

    • 介绍
    • 基础
      • MVVM模型
      • 数据绑定
      • 指令
        • 事件修饰符
        • v-model修饰符
        • v-for
      • 自定义指令
      • 键盘事件
      • 计算属性
      • 监听属性
      • 过滤器
      • 绑定class
      • 绑定style
      • 生命周期
      • 组件
        • 父传子
        • 子传父
        • 全局事件总线
        • 消息订阅与发布(pubsub)
      • 动画
        • 自定义过渡类名
        • 配置
      • 插槽
    • Vuex
    • Vue-Router
    • Vue-CLI
    • Vue3
    • 项目搭建
    • Vue3

  • uni-app

  • 前端
  • Vue
深海
2023-03-03
目录

基础

Vue官网 (opens new window)

# MVVM模型

  • M:模型(Model)对应data中的数据
  • V:视图(View) 模版
  • VM:视图模型(ViewModel) Vue中的实例对象

# 数据绑定

// 原数据
let p = {
    name: '张三',
    age: 20
}
let person = {}
Object.defineProperty(person,'age',{
    value:"",          // 值
    enumerable:true,   // 控制属性是否可以枚举,默认值为false
    writable:true,     // 控制属性是否可以被修改,默认值为false
    configurable:true, // 控制属性是否可以被删除,默认值为false
    // 当有设置person.age时,set(setter)就会被调用
    set(value){
        number = value;
    },
    // 当有读取person.age时, get函数(getter)就会被调用
    get(value){
        return number;
    }
})
// vue中将data中的数据进行数据代理到vm下,且_data中进行了数据劫持,
// 当_data中改变则模版中引用该数据同时也发生变化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 指令

  • 内置指令
指令 说明 指令 说明
v-bind 单项绑定 v-model 双向数据绑定
v-for 遍历数组/对象/字符串 v-on 绑定事件监听
v-if 条件渲染 v-show 控制节点是否展示
v-text 节点中渲染文本内容 v-html 渲染包含html结构的内容 有安全性问题
v-cloak 隐藏尚未完成编译的DOM模板 v-once 仅渲染元素和组件一次,并跳过之后的更新
v-pre 跳过该元素及其所有子元素的编译

# 事件修饰符

修饰符 描述 修饰符 描述
.prevent 阻止默认事件 .stop 阻止事件冒泡
.once 事件只触发一次 .capture 使用事件的捕获模式
.self 只有event.target是当前操作的元素时才会触发事件 .passive 事件的默认行为立即执行,无需等待事件回调执行完毕
.native 组件的根元素上绑定事件

# v-model修饰符

修饰符 描述 修饰符 描述 修饰符 描述
.number 输入字符串转为有效数字 .trim 首尾空格过滤 .lazy 失去焦点再收集数据

# v-for

遍历数组 / 对象

  • 对象 v-for="(item,key,index) in myObject"
    • item ----- 值 -----
    • key ----- key -----
    • index ----- 索引 -----

key的作用

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,之后Vue会进行【新旧虚拟DOM】的差异比较

  • 比较规则
    1. 旧虚拟DOM中找到了与新虚拟DOM相同的key

      (1) 若虚拟DOM中内容没变,直接使用之前真实的DOM
      (2) 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM

    2. 旧虚拟DOM中未找到与新虚拟DOM相同的key

      直接创建新的真实DOM,之后渲染到页面上

  1. 应如何选择key
    • 最好使用每条数据的唯一标识作为key
    • 如果不存在对数据的逆序添加,逆序删除等破坏顺序操作,仅用于渲染列表用于展示,可以使用index作为key

# 自定义指令

// 局部指令
directives:{指令名,配置对象}   directives:{指令名,回调函数}
// 全局指令
Vue.directive(指令名,配置对象)  Vue.directive(指令名,回调函数)
// 配置对象中常用的回调函数
bind      // 只调用一次,指令第一次绑定到元素时调用,可以定义一个在绑定时执行一次的初始化动作。
inserted  // 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
update    // 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值。
componentUpdated  // 被绑定元素所在模板完成一次更新周期时调用。
unbind    // 只调用一次, 指令与元素解绑时调用。
bind      // 指令与元素成功绑定时调用
inserted  // 指令所在元素被插入页面时调用
update    // 指令所在模版结构被重新解析时调用 
1
2
3
4
5
6
7
8
9
10
11
12
13

批量注册指令,新建index.js文件

MK麦客 (opens new window)

import copy from './copy'
const directives = {
  copy,
}
 
export default {
  install(Vue) {
    Object.keys(directives).forEach((key) => {
      Vue.directive(key, directives[key])
    })
  },
}
1
2
3
4
5
6
7
8
9
10
11
12

指令功能copy.js

点击查看
const copy = {
  bind(el, { value }) {
    el.$value = value
    el.handler = () => {
      if (!el.$value) {
        // 值为空的时候,给出提示。可根据项目UI仔细设计
        console.log('无复制内容')
        return
      }
      // 动态创建 textarea 标签
      const textarea = document.createElement('textarea')
      // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
      textarea.readOnly = 'readonly'
      textarea.style.position = 'absolute'
      textarea.style.left = '-9999px'
      // 将要 copy 的值赋给 textarea 标签的 value 属性
      textarea.value = el.$value
      // 将 textarea 插入到 body 中
      document.body.appendChild(textarea)
      // 选中值并复制
      textarea.select()
      const result = document.execCommand('Copy')
      if (result) {
        console.log('复制成功') // 可根据项目UI仔细设计
      }
      document.body.removeChild(textarea)
    }
    // 绑定点击事件,就是所谓的一键 copy 啦
    el.addEventListener('click', el.handler)
  },
  // 当传进来的值更新的时候触发
  componentUpdated(el, { value }) {
    el.$value = value
  },
  // 指令与元素解绑的时候,移除事件绑定
  unbind(el) {
    el.removeEventListener('click', el.handler)
  },
}
export default copy
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

在main.js中引入并注册

import Vue from 'vue' import Directives from 'index.js' Vue.use(Directives)

页面中调用即可
```html
<button v-copy="copyText">复制</button>
1
2
3

# 键盘事件

  1. Vue中常用的键盘别名
    别名 别名 别名 别名
    回车 enter 删除 delete 空格 esc 空格 space
    换行 tab(需配合keydown去使用) 上 up 下 down 左 left
    右 right
  2. 注意
// 1.Vue中如捕获多个单词的键盘,需要用-隔开,如@keyup.caps-lock="mykey"
// 2.系统修饰键
   ctrl、alt、shift、meta
   (1).配合keyup使用:按下修饰键的同时,再按下其他键,之后释放其他键,事件才会触发。
   (2).配合keydown使用:正常触发事件即可。
// 3.使用keyCode指定具体的按键(不推荐)
// 4.自定义键名
   Vue.config.keyCodes.自定义键名 = 键名
1
2
3
4
5
6
7
8

# 计算属性

  1. 定义: 通过已有属性计算得来
  2. 原理 : 底层借助Object.defineproperty方法提供的getter和setting。
  3. get函数执行时机
    • 初次读取会执行一次
    • 依赖的数据发生变化时会再次被调用
  4. 优势
    • 与methods实现相比,内部有缓存机制(复用,效率更高)
  5. 注意
    • 计算属性会出现在vm上,点击读取即可
    • 当计算属性要被修改,那必须些set函数去响应修改,且set函数中要引起计算时依赖的数据 发生变化才行
computed:{
    count :{
        // 调用触发
        get(){},
        // 改变触发
        set(value){}
    }
    // 计算属性简写(只考虑读取可使用)
    count(){ return 'content'}
},
1
2
3
4
5
6
7
8
9
10

# 监听属性

用于监听data中与computed中的属性,当监视的属性发生变化时,回调函数自动调用

watch:{
    city:{
        deep:true,       // 深度监听对象内部值的改变
        immediate:true,  // 初始化时让handler调用一下
        // handler发生变化时调用
        handler(newValue,oldValue){}
    },
    // 也可单独监听对象中某个属性的变化
    'number.a'(newVal,oldVal){},
    // 简写
    city(newValue,oldValue){}
}
// 组件实例中调用$watch
vm.$watch('city',{
    immediate:true,
    handler(newValue,oldValue){}
})
// 简写(不能使用其他属性)
vm.$watch('city', function(newValue,oldValue){})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 过滤器

对要显示的数据进行特定格式化后再显示(仅适用于一些简单逻辑)

filters:{
    getTime(val){
        return moment(val).format('YYYY年MM月DD HH:mm');
    }
}
// 全局过滤器
Vue.filter(name,callback)
// 多个过滤器也可以串联
{{ time | 过滤器名1 | 过滤器名2 }}  v-bind:属性=" xxx | 过滤器名"
1
2
3
4
5
6
7
8
9

# 绑定class

  • 字符串绑定
<div class="box" :class="bg"></div>
1
  • 数组绑定
<div :class="['a','b']"></div>
<div :class="[obj.isActive ? 'a1' : '','errorClass']"></div>
<!-- a1 和 'a1' 两种都可以 -->
<div :class="[{a1:obj.isActive},'errorClass']"></div>
1
2
3
4
  • 对象绑定
<div :class="{ active: isActive ,'text-danger': hasError}"></div>
<div :class="classObject"></div>
1
2
data(){
  return{
    classObject: {
      active: true,
      'text-danger': false
    }
  }
}
1
2
3
4
5
6
7
8
  • 计算属性绑定
<div :class="classObject"></div>
1
computed:{
  classObject(){
    return{
      active:this.obj.isActive,
      'selected':this.obj.status == 'error'
    }
  }
}
1
2
3
4
5
6
7
8

# 绑定style

注意

  • 凡是有-的style属性名都要变成驼峰式,比如font-size要变成fontSize
  • 除了绑定值,其他的属性名的值要用引号括起来,比如color:#00a2ff'而不是 color:#00a2ff
  • 数组绑定
<div :style="[baseStyles, overridingStyles]"></div>
<div :style="[{color:(index == 1 ? 'green':'red')},{fontSize:'18px'}]"></div>
1
2
  • 对象绑定
<div :style="{color: activeColor, fontSize: fontSize + 'px' }"></div>
<div :style="{color:index == 1 ? 'blue' : 'red'}"></div>
1
2
  • 三元表达式
<div :style="activeLayerName === 1?'font-weight:700' : 'font-weight:400'"></div>
1

# 生命周期

  • beforeCreate

    初始化生命周期、事件,但数据代理还未开始,无法访问data数据及methods中的方法

  • created

    初始化数据代理、数据监测,可以访问data数据及methods中的方法

  • beforeMount

    页面显示的是未经Vue编译的DOM结构,所有对DOM的操作,最终都没效果

  • mounted

    页面显示的是Vue编译的DOM结构,用于初始化操作

  • beforeUpdate

    数据是新的,页面是旧的,页面尚未和数据保持同步

  • updated

    页面和数据保持同步

  • beforeDestroy

    开始执行销毁过程

  • destroyed

    销毁已结束

# 组件

定义

用来实现局部功能效果的代码集合

  • 定义组件
const school = Vue.extend({
    template:`<div>{{user}}</div>`,
    // 组件中的data必须写成函数,避免组件被复用时,数据存在引用关系
    data(){
        return{
            user:"子组件"
        }
    }
})
1
2
3
4
5
6
7
8
9
  • 注册组件
// 局部注册
new Vue({
    el:"#root",
    components:{
        school
    }
})
// 全局注册
Vue.component('组件名',组件)
1
2
3
4
5
6
7
8
9
  • this.$refs

    是一个对象,持有已注册过的所有子组件。 ref为子组件指定一个名称,通过this.$refs.ref指定的子组件名称 即可获得对该子组件的操作 (包括data中定义的数据和methods中定义的方法)

  • this.$parent

    可以访问到父组件上所有的数据在子组件中使用

    注意

    当遇到this.$parent.数据获取父组件的数据得到undefined的情况时,是因为父组件在调用子组件的时候,在子组件的外层包裹了一层UI组件的某个组件

    //外层包裹了几个组件就需要用几个$parent,即可解决
    this.$parent.$parent.数据
    
    1
    2
  • this.$root

    可以直接操作当前组件的所有祖先组件的根组件

  • this.$children

    是一个数组,可以操作当前组件的所有子组件

# 父传子

// 父组件
<Floating :title="str" ref="floating"></Floating>
// 子组件props接收的三种方式
props:['title']
props:{
  // 表示传入的值是Number或者String类型
  content: [Number, String],
  // 传入布尔类型的值
  content: Boolean,
}
props: {
  title: {
    type: String, // 传递的类型
    required: true, // 值必传
    default: "我是默认的", // 默认传递的值
  },
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 子传父

自定义事件

// 子组件使用$emit()
valueTransfer(){
  this.$emit('getValue','传递的值')
}
// 父组件接收
// @或v-on
<Floating :title="str" ref="floating" @getValue="getValue"></Floating>
methods:{
  getValue(value){}
}
// 2.使用ref
<Floating ref="floating"></Floating>
mounted(){
  // 这种方式更加灵活,如延迟几秒...
  this.$refs.xxxx.$on('getValue',(value)=>{})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 全局事件总线

组件的通信方式,适用于任意组件的通信(GlobalEventBus)

  1. 安装全局事件总线
new Vue({
  render: h => h(App),
  beforeCreate(){
    Vue.prototype.$bus = this;
  }
}).$mount('#app')
1
2
3
4
5
6
  1. 适用事件总线
// A组件想要接收数据,则A组件给$bus绑定自定义事件
mounted(){
  this.$bus.$on('getData',(value)=>{})
},
// B组件提供数据
methods:{
  this.$bus.$emit('getData',数据)
}
1
2
3
4
5
6
7
8
  1. 解绑当前使用的事件
// 哪个组件使用该事件接收的数据,哪个组件进行解绑
this.$off('事件名')             // 解绑单个
this.$off(['事件名1','事件名2']) // 解绑多个
this.$off()                    // 全部解绑
beforeDestroy(){
  this.$bus.$off('getData')
},
1
2
3
4
5
6
7

# 消息订阅与发布(pubsub)

用于组件通信,适用于任意组件

// 1.安装
npm i pubsub-js
import pubsub from 'pubsub-js'
// 2.A组件需要接收数据,则在A组件中订阅消息并取消订阅
mounted(){
  const pubId = pubsub.subscribe('getData',(msgName,data)=>{
    console.log(msgName,data)
  })
}
beforeDestroy(){
  pubsub.unsubscribe(pubId)
},
// 3.B组件用于提供数据
pubsub.publish('getData',数据)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 动画

类名 说明 类名 说明
v-enter 进入的起点 v-enter-to 进入的终点
v-leave 离开的起点 v-leave-to 离开的终点
v-enter-active 进入过渡过程中 v-leave-active 离开过渡过程中

# 自定义过渡类名

  • enter-class
  • enter-active-class
  • enter-to-class (2.1.8+)
  • leave-class
  • leave-active-class
  • leave-to-class (2.1.8+)

# 配置

  • mode 过渡模式
    • in-out:新元素先进行过渡,完成之后当前元素过渡离开。
    • out-in:当前元素先进行过渡,完成之后新元素过渡进入
  • appear 初始渲染的过渡
<transition
  mode="out-in"
  appear
></transition>
1
2
3
4

# 插槽

作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于父组件 ===> 子组件

  • 默认插槽
<!-- 子组件 -->
<div class="tion">
  <slot>默认内容</slot>
</div>
<!-- 父组件调用 -->
<List>
  <div>内容</div>
</List>
1
2
3
4
5
6
7
8
  • 具名插槽
<!-- 子组件 -->
<div class="tion">
  <!-- 指定插槽名 -->
  <slot name="content">默认内容</slot>
</div>
<!-- 父组件调用 -->
<List>
  <h3>标题</h3>
  <div slot="content">内容</div>
  <!-- template中可以使用v-slot:content这种写法 slot="content"也可以 -->
  <template v-slot:content></template>
</List>
1
2
3
4
5
6
7
8
9
10
11
12
  • 作用于插槽

数据在组件的自身,但数据生成的结构需要组件的使用者来决定。

<!-- 子组件 -->
<div class="tion">
  <!-- 数据在组件内,也可以传多个 -->
  <slot :cxd="books" :username="name"></slot>
</div>
<!-- 父组件调用 -->
<List>
  <!-- 
    scope 和 slot-scope语法都可以使用
    scope="{book}" 也可以使用解构赋值
   -->
  <template slot-scope="book"></template>
</List>
1
2
3
4
5
6
7
8
9
10
11
12
13
上次更新: 2024/10/09, 16:59:47
介绍
Vuex

← 介绍 Vuex→

最近更新
01
TypeScript是什么
06-15
02
项目搭建
05-21
03
Prettier
02-27
更多文章>
Theme by Vdoing | Copyright © 2022-2025 京ICP备2020044002号-4 京公网安备11010502056618号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式