Vue简介

  • 框架类型
    • 动态构建用户界面的 渐进式JavaScript 框架
  • 使用模式
    • 遵循 MVVM模式
  • 与其他JS框架特点
    1. 借鉴 Angular 的 模板数据绑定 技术
    2. 借鉴 React 的 组件化虚拟DOM 技术

基础语法


安装

  • <script>引入
    • 本地引入
    • CDN加速网络引入
  • npm引入
    • npm install vue

语法前提

使用Vue语法前需要满足的条件和需要了解的知识点


Vue容器 & Vue实例

  • 创建 Vue容器
    1
    2
    3
    4
    5
    <body>
    <div id="root">
    Vue容器
    </div>
    </body>
  • 创建 Vue实例
    1
    2
    3
    4
    5
    <script>
    const v = new Vue({
    el:"#root" //el用于指定当前Vue实例为哪个容器服务,通常值为css选择器字符串
    })
    </script>

工作流程

  1. 执行 Vue实例 时,会将 Vue容器 拿来进行解析
  2. 发现 Vue容器 有Vue特定语法,将 Vue实例 中的数据与 Vue容器 对应位置数据进行替换
  3. 生成新的 Vue容器
  4. 然后使用新的 Vue容器 替换掉旧的 Vue容器

规则特性

  1. 一个 Vue实例 对应一个 Vue容器
    1. 【多个 Vue容器】——【一个 Vue实例】 :只绑定第一个 Vue容器
    2. 【一个 Vue容器】——【多个 Vue实例】 :只绑定第一个 Vue实例,并且控制台报错
  2. Vue实例 中data的数据发生改变,页面中 Vue容器 中对应位置数据也会自动更新

Vue模板

  • Vue容器 中的代码称为 Vue模板
  1. Vue实例
    • le 指定的元素,<div id='root'>...</div> 标签和标签内所有内容一起称为模板
  2. Vue组件
    • Vue实例 template 定义的元素(不包含 el 指定元素),称为模板

模板语法

Vue模板 中使用的 Vue语法 ,就称为 模板语法


插值语法

解析标签内容

Vue模板 中使用 {{ }} 用于将数据插入模板,就称为 插值语法
语法值为 js表达式Vue实例属性

1
2
3
4
// Vue模板
<div id="root">
{{name}}
</div>
1
2
3
4
5
6
7
//Vue实例
const v = new Vue({
el:"#root",
data:{
name:"Vue模板语法数据"
}
})

输出结果


指令语法

解析标签本身

使用 v- 开头的指令的 Vue语法 ,就称为 指令语法
语法值为 js表达式Vue实例属性


数据绑定

通过 数据绑定指令 给元素属性绑定 Vue实例 数据


单向绑定
  1. 渲染的数据只能根据 Vue实例 中的数据进行改变
  2. v-bind 声明的属性,其值为表达式
  3. 如果绑定的值为布尔值,则动态决定标签中是否添加此属性

常规:v-bind:xxx = “ttt”
简写::xxx = “ttt”

  • xxx:标签属性名
  • ttt:标签属性值
1
2
3
4
5
6
7
8
9
10
11
12
13
<div v-bind:title="bd">单向数据绑定</div> <!--常规-->
<div :title="bd">单向数据绑定</div> <!--简写-->

<div :title="false">单向数据绑定</div> <!--渲染的元素没有title属性-->
<div :title="cz">单向数据绑定</div> <!--渲染的元素没有title属性-->

new Vue({
el:"#root",
data:{
bd:"绑定数据",
cz:false
}
})

绑定样式

绑定 class属性

  • class属性v-bind:class 可以同时存在
    1. class属性 :用来定义不变的 class类名
    2. v-bind:class :用来定义动态改变的 class类名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style>
.ys1{
background-color:red
}
.ys2{
border:1px solid green
}
.ys3{
border:2px solid blue
}
.ys4{
color:yellow
}
</style>
  • v-bind:class 的值可以是不同数据类型(字符串、对象、数组)
    1. 字符串
      • 绑定的 类名 不确定,需要动态 修改类名
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        <div id="root">
        <p class="ys1" :class="ys_name">这是内容</p>
        </div>

        <script>
        var vm = new Vue({
        el:"#root",
        data:{
        ys_name:"ys2"
        }
        })
        </script>
    2. 数组
      • 绑定的 类名类个数 都不确定,需要动态 修改类名增减类名
      • 数组元素: class类名的字符串
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        <div id="root">
        <p class="ys1" :class="arr_ys">这是内容</p>
        </div>

        <script>
        var vm = new Vue({
        el:"#root",
        data:{
        arr_ys:["ys1","ys4"]
        }
        })
        </script>
    3. 对象
      • 绑定的 类名类个数 都确定,但是需要动态 启用或关闭样式
      • 对象属性名: class类名
      • 对象属性值:布尔值(设置是否启用)
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        <div id="root">
        <p class="ys1" :class="obj_ys">这是内容</p>
        </div>

        <script>
        var vm = new Vue({
        el:"#root",
        data:{
        obj_ys:{
        ys1:true,
        ys2:true,
        ys3:false
        }
        }
        })
        </script>

绑定 style属性

  • style属性v-bind:style 可以同时存在

    1. style属性 :用来定义不变的 css样式
    2. v-bind:style :用来定义动态改变的 css样式
  • v-bind:style 的值的数据类型为 对象数组

    1. 对象
      • 对象属性:css样式属性(短横线链接的css属性,需要使用驼峰写法)
      • 对象属性值:css样式属性值 字符串
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        <div id='root'>
        <p style="color:red;" v-bind:style="bc">内容</p>
        </div>

        <script>
        var vm = new Vue({
        el:"#root",
        data:{
        bc:{
        backgroundColor:"red"
        }
        }
        })
        </script>
    2. 数组
      • 动态 增减修改 同一类css属性样式(也可以不是一类),使用数组形式,方便修改
      • 数组元素:v-bind 绑定css样式的对象形式
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        <div id='root'>
        <p style="color:red;" v-bind:style="arr_ys">内容</p>
        </div>

        <script>
        var vm = new Vue({
        el:"#root",
        data:{
        arr_ys:[
        {
        borderColor:"red",
        borderStyle:"solid"
        },
        {
        color:"red"
        }
        ]
        }
        })
        </script>

双向绑定

既能根据 Vue实例 中的数据渲染页面,也能通过页面输入数据修改 Vue实例 中的数据
只要在表单元素输入数据, Vue实例 中的数据立即发生改变
只能应用在 表单类元素vule属性
常规:v-model:value = “xxx”
简写:v-model = “xxx”
xxx:输入框的内容

1
2
3
4
5
6
7
8
9
<input v-model:value="bd"/> <!--常规-->
<input v-model="bd"/> <!--简写-->

new Vue({
el:"#root",
data:{
bd:"绑定数据"
}
})

绑定表单
  1. 绑定 text 文本输入框
    • v-model 收集的是 value 中的数据
    • 通用或简写方式也是将 valueVue实例数据 进行绑定
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      <!-- 将输入框输入的内容(value的值),保存到Vue实例的name1,name2属性中 -->

      <div id="root">
      <input type="text" v-model="name1"/>
      <input type="text" v-model:value="name2"/>
      </div>

      <script>
      var vm = new Vue({
      el:"#root",
      data:{
      name1:"xxxx",
      name2:"yyyy"
      }
      })
      </script>
  2. 绑定 radio 单选框
    • 正常情况标签必须添加 value属性
    • 正常情况Vue实例数据为 字符串
    • v-model 简写,接收数据到 Vue实例属性
    • 标签有value属性:v-model 收集的是 value 的值
    • 标签无value属性:v-model 收集的是 null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- value属性必须定义 -->
<!-- name属性将单选框进行分组,三选一 -->
<!-- v-model 接收 value 值,并保存到Vue实例中的namedata属性 -->

<div id="root">
<input type="radio" value="篮球" name="体育" v-model="namedata"/>
<input type="radio" value="足球" name="体育" v-model="namedata"/>
<input type="radio" value="排球" name="体育" v-model="namedata"/>
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
namedata:"xxxx"
}
})
</script>
  1. 绑定 checkbox 多选框
    • 正常情况标签必须添加 value属性
    • 正常情况Vue实例数据为 数组
    • 绑定的data数据非数组
      • 初始化渲染:根据数据转换的布尔值(Vue实例中数据没有实际转换),决定初始化渲染是否选中标签
      • 点击多选框:修改实例数据为checked布尔值(根据是否勾选,修改vue实例数据值为布尔值)
    • 绑定的data数据数组
      • 标签有value属性:选中标签的value值作为数组元素
      • 标签无value属性:数组添加一个null元素,并全选所有标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- value属性必须定义 -->
<!-- name属性将单选框进行分组,三选一 -->
<!-- v-model 接收 value 值,并保存到Vue实例中的namedata属性 -->

<div id="root">
<input type="checkbox" value="篮球" v-model="namedata"/>
<input type="checkbox" value="足球" v-model="namedata"/>
<input type="checkbox" value="排球" v-model="namedata"/>
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
namedata:["篮球","足球"] // 篮球,足球复选框被选中,其元素value被存储
}
})
</script>

双向绑定修饰符

.lazy <input type="text" v-model.lazy="datas" />

失去焦点再接收数据。默认输入数据立即改变vue实例中的数据。

.number <input type="number" v-model.number="datas" />

接收的数据转换为数值类型,等同于调用 parseInt 方法

.trim <input type="text" v-model.trim="datas" />

接收的数据清除首位空格


事件绑定


事件声明

常规:v-on:xxx = “fff”
简写:@xxx = “fff”

  • xxx:事件名称
  • fff:事件处理函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 函数声明中,第一个接收到的实参是 事件对象
<button v-on:click="ff">按钮</button>

// 函数声明中,第一个接收到的实参是 传入的1
<button @click="ff(1,2)">按钮</button>

new Vue({
el:"#root",
data:{},
methods:{
ff(event,a){ // 函数绑定时,是否传入参数,第一个实参会不同(事件对象/实参数据)
...
}
}
})

事件处理的特点

  • 声明位置:事件处理函数设置在 methods对象
  • 调用方式:事件处理函数会配置在 Vue实例 上,由 Vue实例 直接调用
  • this关键字:this 指向 Vue实例 。箭头函数指向 window

参数传递

  • 无参
    • 元素—绑定事件
      • 不需要用小括号 ( )
    • 实例—定义事件
      • 获取 事件对象 ,需要定义形参,第一个参数为 事件对象
  • 有参
    • 元素—绑定事件
      • 获取事件对象,需要传入关键字 $event
    • 实例—定义事件
      • 根据参数位置接收参数

事件修饰符

使用 .xxx 修饰符,对事件进行额外功能的配置 @click.prevent="ff"
事件修饰符可以连续书写,根据顺序执行相关额外操作 @keydown.stop.prevent="ff"

  1. prevent:阻止默认事件
  2. stop:阻止事件冒泡
  3. once:事件只触发一次
  4. capture:设置事件捕获模式
  5. self:只有 event.target 是当前元素才触发事件。(非因冒泡或捕获触发的事件)
  6. passive:事件的 默认行为立即执行,无需等待事件回调执行完毕

键盘事件

按下键盘任意键,触发事件

按下:keydown @keydown='ff'
弹起:keyup @keyup='ff'

按下指定键,触发事件

按键别名作为修饰符,即可指定按键触发事件 @keyup.enter="ff"

键名的注意事项

  • Vue未提供别名的按键,使用按键原始名,多个单词用短横线链接
  • 使用 keycode(键码) 也可以绑定指定按钮触发事件,但是使用 keycode 不建议使用
  • 指定键名:Vue.config.keyCodes.自定义键名 = 键码(keycode)

Vue预定义的键名

  1. 回车 => enter
  2. 删除 => delete (删除/退格)
  3. 退出 => esc
  4. 空格 => space
  5. 换行 => tab (只对 keydown 键有用)
  6. 上 => up
  7. 下 => down
  8. 左 => left
  9. 右 => right
  10. 字母 => 字母

系统组合键,触发事件 ( ctrl、alt、shift、meta(window键) )
配置系统键和指定按键同时作为修饰符,即可设置指定组合触发事件

  • keyup
    • 按下系统键,并且按下其他键,然后释放其他键,事件才会触发
    • @keyup.alt="ff"
    • @keyup.alt.enter="ff"
  • keydown
    • 按下系统键,并且按下其他键,事件就会触发
    • @keydown.alt="ff"
    • @keydown.alt.enter="ff"

标签渲染

用来控制标签元素的显示方式的指令语法


条件渲染

根据指令语法值 true/false 控制元素的 显示和隐藏


v-show

根据指令值,决定元素是否进行显示

  1. true:显示 / false:隐藏
  2. 指令值会自动进行类型转换(转为 Boolean)
  3. 元素不被移除,只是进行隐藏,隐藏时DOM结构中也有元素,可以通过js获取到元素(等同设置css样式:display: none)
  4. 适合频繁操作
1
2
3
4
5
6
7
8
9
10
11
12
<div id="root">
<p v-show="vs">显示内容</p>
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
vs:true
}
})
</script>

v-if

根据指令值,决定元素是否进行显示

  1. true:显示 / false:隐藏
  2. 指令值会自动进行类型转换(转为 Boolean)
  3. 元素会被移除和添加,移除时DOM结构中没有元素,不可以通过js获取到元素
  4. 适合切换不频繁场合
1
2
3
4
5
6
7
8
9
10
11
12
<div id="root">
<p v-if="vs">显示内容</p>
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
vs:true
}
})
</script>

v-if、v-else-if、v-else

  1. 结构不可以被打断。(具有这些指令的元素之间不可以插入其他元素)
  2. 前面指令值为true,后面元素的指令将不再执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="root">
<p v-if="vs == 1">显示内容</p>
<p v-else-if="vs == 2">显示内容</p>
<p v-else-if="vs == 3">显示内容</p>
<p v-else="vs == 4">显示内容</p>
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
vs:2
}
})
</script>

列表渲染 v-for

使用 v-for="(item,index) in objarr" 指令语法遍历(对象、数组、字符串、数字),并根据遍历次数创建相应个数绑定元素,并接收遍历元素的相关数据

  1. 遍历数组
    • 元素的参数
      1. 参数1:数组元素(只有一个参数时:数组元素)
      2. 参数2:数组下标
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        <div id="root">
        <p v-for="(item,index) in name_arr" :key="index">{{item,name}}:{{item.age}}</p> <!---获取元素两个参数-->
        <p v-for="item in name_arr">{{item,name}}</p> <!--获取元素单个参数-->
        </div>

        <script>
        var vm = new Vue({
        el:"#root",
        data:{
        name_arr:[
        {
        name:"小明",
        age:"19"
        },
        {
        name:"小红",
        age:"20"
        }
        ]
        }
        })
        </script>
  2. 遍历对象
    • 元素的参数
      1. 参数1:对象属性值(只有一个参数时:对象属性值)
      2. 参数2:对象属性名
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        <div id="root">
        <p v-for="(obj_value,obj_key) in name_obj" :key="obj_key">{{obj_key}}:{{obj_value}}</p> <!--获取元素两个参数-->
        <p v-for="value in name_arr">{{value}}</p> <!--获取元素单个参数-->
        </div>

        <script>
        var vm = new Vue({
        el:"#root",
        data:{
        name_obj:{
        name1:"小明",
        name2:"小红",
        name3:"小兰"
        }
        }
        })
        </script>
  3. 遍历字符串
    • 元素的参数
      1. 参数1:单个字符(只有一个参数时:单个字符)
      2. 参数2:字符下标
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        <div id="root">
        <p v-for="(str,index) in name_string" :key="index">{{str}}:{{index}}</p> <!--获取元素两个参数-->
        <p v-for="str in name_arr">{{str}}</p> <!--获取元素单个参数-->
        </div>

        <script>
        var vm = new Vue({
        el:"#root",
        data:{
        name_string:"abcde"
        }
        })
        </script>
  4. 遍历数字
    • 元素的参数
      1. 参数1:从1开始的数值(只有一个参数时:从1开始的数值)
      2. 参数2:从0开始的下标
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        <div id="root">
        <p v-for="(num,index) in 5" :key="index">{{num}}:{{index}}</p> <!--获取元素两个参数-->
        <p v-for="num in name_arr">{{num}}</p> <!--获取元素单个参数-->
        </div>

        <script>
        var vm = new Vue({
        el:"#root",
        data:{}
        })
        </script>

:key属性

:key="xx" 给循环遍历数据创建的节点指定一个唯一标识
只用于 Vue 内部使用,DOM结构不生成 key 属性

列表渲染的流程

  1. 根据key属性, 对比虚拟DOM
  2. 根据对比结果,决定是使用 旧真实DOM元素 ,还是 新生成DOM元素
  1. 根据数据生成 虚拟DOM,虚拟DOM包含 key属性
  2. 根据 虚拟DOM 直接生成 真实DOM
  3. 修改数据 之后,生成新的 虚拟DOM
  4. 新旧 虚拟DOM 根据 key属性 进行匹配元素
  5. 元素匹配上之后对比 虚拟DOM的元素的内容
  6. 不同的 虚拟DOM元素的内容 ,使用 新虚拟DOM 生成 新内容。 相同 虚拟DOM元素内容 ,则使用 旧的真实DOM元素的内容(虚拟DOM元素内容,可以部分生成,部分引用旧的)
  7. 新旧 虚拟DOM 没有匹配到具有相同 key属性虚拟DOM元素 ,则使用 新虚拟DOM 生成 新真实DOM元素

不使用key属性出现的问题

  1. 新生成的虚拟DOM,其key属性使用的是数据下标
    • 如果插入新数据,新虚拟DOM下标依旧从0开始,但是内容与旧虚拟DOM不同,因此会使用新虚拟DOM重新生成真实DOM元素
    • 会使得效率低下
  2. 如果旧的真实DOM元素更改了内容,新真实元素部分内容引用的是旧真实元素内容,部分内容使用的是新数据内容,则对应关系发生混乱

开发中如何选择 key

  1. 每条数据人为设置唯一标识数据
  2. 如果只是显示数据,不修改数据顺序,并且不修改DOM元素内容,则没有影响

其他内置指令

内置指令,Vue预定义的指令都是内置指令


v-text

绑定数据以文本方式替换掉所在元素的内容

  1. 不支持结构解析:将绑定数据作为 文本内容,渲染到元素中(不会将html标签转换为DOM节点)
  2. 替换元素内容:会替换掉元素本来的内容
1
2
3
4
5
6
7
8
9
10
11
12
<div id="root">
<p v-text="data_val">123</p> <!--页面显示的内容是 <span>456</span>-->
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
data_val:"<span>456</span>"
}
})
</script>

v-html

绑定数据以html结构方式替换掉所在元素的内容

  1. 支持结构解析:会将具有html结构的文本数据作为 html结构,渲染到元素中(会将html标签转换为DOM节点)
  2. 替换元素内容:会替换掉元素本来的内容
  3. 安全问题
    1. 容易导致 XSS 攻击
    2. 如果是将带有html节点的文本直接渲染到页面,可以通过上传具有发送请求功能的文本标签,Vue会将此文本渲染到页面,其他用户点击此html标签,会进行跳转并获取当前页面的cookie
1
2
3
4
5
6
7
8
9
10
11
12
<div id="root">
<p v-html="data_val">123</p> <!--页面显示的内容是 456-->
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
data_val:"<span>456</span>"
}
})
</script>

v-cloak(没有值)
  1. 元素会添加一个 v-cloak 属性
  2. Vue实例创建完成并接管容器后,会删除元素上的 v-cloak 属性

配合 css属性选择器 可以在 Vue实例 接管 Vue容器 之前,隐藏显示出来的 { { xxx } } 插值语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<style>
[v-cloak] {
display:none <!-- 3. 在Vue实例接管容器之前,隐藏此元素 -->
}
</style>

<div id="root">
<p v-cloak> {{ data_val }} </p> <!-- 1. Vue实例接管容器之前,页面显示 {{ data_val }} -->
</div>

<script src="https://xxx.xx.xxx.js"></script> <!-- 2. 这个请求消耗时间,导致html已经渲染显示,但是Vue实例还没有创建无法接管容器,使得页面显示了 Vue 的插值语法 -->

<script>
var vm = new Vue({ // 4. Vue实例接管容器后,会自动删除 v-cloak 指令属性
el:"#root",
data:{
data_val:"内容"
}
})
</script>

v-once(没有值)

节点在初次动态渲染后,就视为静态内容,以后数据的改变不会渲染到具有 v-once 指令的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="root">
<p v-once>初始化的值:{{data_val}}</p> <!-- 初次渲染数据为1后,一直保持不变 -->
<p>当前值:{{data_val}}</p> <!-- 点击增加1按钮后的值 -->

<button @click="data_val++">增加值</button> <!-- 点击数值加1 -->
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
data_val:1
}
})
</script>

v-pre(没有值)

跳过Vue对节点的编译,将节点直接渲染到页面
代码书写成什么样,就渲染成什么样,具有Vue语法也直接作为元素内容显示,不对Vue语法进行编译处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="root">
<p v-pre>{{data_val}}</p> <!-- html源代码:<p v-pre>{{data_val}}</p> -->

<button @click="data_val++">增加值</button> <!-- html源代码:<button @click="data_val++">增加值</button> -->
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
data_val:1
}
})
</script>

实例结构

el:绑定

  1. 实例化Vue对象时,指定参数el值
    • 参数:css选择器、元素js对象
  2. 通过Vue实例调用 $mount() 方法,将实例与容器进行绑定
    • 参数:css选择器、元素js对象
1
2
3
4
5
6
7
8
9
<div id='root'></div>

var v = new Vue({
//el:"#root"
data:{
bd:"数据"
}
})
v.$mount("#root")

template:模板

流程图
  • Vue实例解析模板流程
    1. 先检查是否有 “el” 配置项,没有的话调用 “vm.$mount(el)”
    2. 然后检查是否有 “template” 配置项
      1. 如果有 “template” 配置项
        1. “template” 配置项内容编译为渲染函数
        2. 使用此渲染函数生成虚拟DOM
      2. 如果们没有 “template” 配置项
        1. 使用 “el” 配置项或 “vm.$mount(el)” 的 outerHTML 生成虚拟 DOM

data:数据结构

  1. 对象
    1
    2
    3
    4
    5
    6
    var v = new Vue({
    el:"#root",
    data:{
    ...
    }
    })
  2. 函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var v = new Vue({
    el:"#root",
    data:function(){
    return {
    ....
    }
    }
    /*
    data()=>{
    return {
    ...
    }
    }
    */
    })
  • 函数式data特点
    • data函数式数据结构,必须 return 返回结果
    • data函数式数据结构,普通函数this指向Vue实例,箭头函数this指向window
    • 组件中的data数据,必须使用函数式数据结构

methods:函数

  1. methods 属性是个对象,用于给 Vue 实例定义方法
  2. methods 中定义的方法,this 指向 Vue 实例
1
2
3
4
5
6
7
8
var vm = new Vue({
methods:{
function fn(){
...
}
}
})


computed:计算属性

通过计算生成的属性。即通过 Object.defineProperty() 函数实现的 Vue实例 中的 get()/set() 属性

通用写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
vue vm = new Vue({
le:"#root",
data:{
name:"xx"
},
computed:{
prop:{
get(){
return this.name+1
},
set(vl){
this.name = vl;
}
}
}
})

简写方式

1
2
3
4
5
6
7
8
9
10
11
12
vue vm = new Vue({
le:"#root",
data:{
name:"xx"
},
computed:{
prop(){ //当计算属性只有 get() 时,可以将计算属性写成函数。等同于计算属性只书写一个 get()
return this.name+1
}
}
}
})

与函数优势

  • 函数
    • 只要data数据更改,就会重新解析模板,重新解析模板就会重新执行模板中使用的函数。效率低
  • 计算属性
    • 内部有缓存机制(复用),效率更高,只有相关操作才会触发计算属性重新执行

计算属性触发条件

  • get()
    1. 初次读取计算属性时调用
    2. 依赖数据发生改变时调用
  • set()
    • 给计算属性赋值时调用

计算属性的特点

  1. vm._data 中没有计算属性,vm._data 中只有 data 中的属性,计算属性 直接添加在 Vue实例 上的,可以直接使用
  2. 计算属性 get()/set() 中的 this 指向 Vue实例。即可通过 this 直接获取 data 中数据

watch:监视属性

用于监视属性是否发生改变,属性发生改变时触发 handler() 监视处理函数

监视属性特点

  1. 也可以监视 计算属性
  2. this 指向 Vue实例
  3. computed 能完成的 watch 都能完成,但是 watch 能完成的 computed 不一定能完成

watch 对象中 配置 需要监视的属性的相关参数

  • watch 配置项的值是对象
    1. 属性名:需要监视的数据名
    2. 属性值:对象。配置监视数据方式
      1. immediate 参数:初始就执行一次监视处理函数
      2. handler 参数:监视处理函数,监视属性发生改变触发此函数
      3. deep 参数:watch 默认 false 不监测对象属性内部数据的变化。即监视属性是对象,其属性值(对象属性的属性的属性的…)的改变不触发监视处理函数。参数设置为 true 即可监视对象属性内部数据的改变

通用写法

初始化配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var vm = new Vue({
el:"#root",
data:{
name:"xxx"
},
watch:{
name:{
immediate:true, //初始就执行一次监视处理函数
deep:true, //深度监视
handler(newValue,oldValue){ //监视处理函数:监视属性发生改变触发此函数
console.log("修改前:"+oldValue+"修改后"+newValue)
}
}
}
})

Vue实例配置

1
2
3
4
5
6
7
8
9
10
11
12
13
var vm = new Vue({
el:"#root",
data:{
name:"xxx"
}
})
vm.$watch("name",{ //通过Vue实例配置进行监视属性
immediate:true, //初始就执行一次监视处理函数
deep:true, //深度监视
handler(newValue,oldValue){ //监视处理函数:监视属性发生改变触发此函数
console.log("修改前:"+oldValue+"修改后"+newValue)
}
})

简写方式

初始化配置

1
2
3
4
5
6
7
8
9
10
11
12
13
var vm = new Vue({
el:"#root",
data:{
name:"xxx"
},
watch:{
//当不需要 deep、immediate 参数时,可以直接将监视属性定义为函数。等同于只有一个 handler 监视属性配置方式
name(newValue,oldValue){
console.log("修改前:"+oldValue+"修改后"+newValue)
}
}
}
})

Vue实例配置

1
2
3
4
5
6
7
8
9
10
11
var vm = new Vue({
el:"#root",
data:{
name:"xxx"
}
})

//当不需要 deep、immediate 参数时,可以直接将第二个参数定义为函数,此函数为 handler 监视处理函数
vm.$watch("name",(newValue,oldValue){
console.log("修改前:"+oldValue+"修改后"+newValue)
})

filters:过滤器

过滤器 是一个预定义的函数,模板中使用 管道符 | 配置过滤器,对模板中使用的数据进行简单的处理,渲染处理后的数据
v-model 双向绑定,不能使用过滤器

  1. 至少设置一个形参 :形参1,固定传入需要处理的数据
    1. 可以不用小括号,表示不传入其他参数,默认只传入处理的数据
    2. 使用小括号传入其他实参,第二个形参开始指向第一个实参
  2. 必须有返回值 :返回值为需要渲染的数据
  3. 并没有改变原始数据 ,是产生新的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="root">
<p>{{ name | nr }}</p>
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
name:"只是数据"
},
filters:{
nr(val){
return val.slice(0,3)
}
}
})
</script>

过滤器传参

  1. 第二个形参指向调用处第一个实参,以此类推
  2. 第一个形参固定默认为需要处理的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="root">
<p>{{ name | nr(3) }}</p>
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
name:"展示的数据"
},
filters:{
nr(val,num){
return val.slice(0,num)
}
}
})
</script>

连续使用过滤器

  1. 连续使用 管道符 | 调用多个过滤器处理数据
  2. 后一个过滤器处理的数据,是前一个过滤器的返回值,以此类推
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="root">
<p>{{ name | nr(3) | nr2 }}</p>
</div>

<script>
var vm = new Vue({
el:"#root",
data:{
name:"展示的数据"
},
filters:{
nr(val,num){
return val.slice(0,num)
},
nr2(val){
return val.slice(0,1)
}
}
})
</script>

局部过滤器和全局过滤器

  1. 局部过滤器:当前Vue实例中定义的过滤器,只能针对当前Vue实例的数据进行处理
  2. 全局过滤器:使用 Vue类函数 filter() 定义的过滤器,所有Vue实例都可以调用
1
2
3
4
5
6
7
8
9
<script>
Vue.filter("过滤器名",function(val){
return val.slice(0,2)
})

var vm1 = new Vue({...})
var vm2 = new Vue({...})
</script>


directives:自定义指令

  1. 自定义的指令,定义时不需要带 v-,调用时需要带 v-
  2. 定义指令的函数(钩子函数) this ,指向 window
  3. 调用时指令绑定的数据,自定义指令时由第二个形参提供
  4. 指令名是多个单词,定义时不能使用 驼峰式 ,必须使用 短横线
  5. 操作属性值,需要绑定元素属性如: <input v-xxx:value="data">

函数形式定义

两个形参

  1. 形参1:指向绑定元素的DOM
  2. 形参2:绑定数据

自定义指令触发条件,等于同时定义 bind、update 钩子函数

  1. 指令与模板绑定时(内存中)
  2. 当Vue模板重新解析时
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<p v-big="n"></p>

<script>
var vm = new Vue({
el:"#root",
data:{
n:1
},
directives:{
big(element,binding){
element.innerText = binding.value * 10; //绑定元素内容增加10倍作为元素内容
}
}
})
</script>

对象形式定义

需要实现预定的钩子函数,在指定情况下触发相关函数

  1. bind:指令与元素成功绑定时(一上来)
  2. inserted:指令所在元素插入页面时
  3. update:指令所在模板重新解析时

钩子函数两个形参

  1. 形参1:指向绑定元素的DOM
  2. 形参2:绑定数据
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
<input type="text" v-big:value="n"/>

<script>
var vm = new Vue({
el:"#root",
data:{
n:1
},
directives:{
big:{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value = binding.value
},
//指令所在元素被插入页面
inserted(element,binding){
element.focus()
},
//指令所在模板被重新解析时
update(element,binding){
element.value = binding.value
}
}
}
})
</script>

全局定义

Vue的类函数 directives 进行定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<p v-big></p>

<script>
Vue.directives("big",{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value = binding.value
},
//指令所在元素被插入页面
inserted(element,binding){
element.focus()
},
//指令所在模板被重新解析时
update(element,binding){
element.value = binding.value
}
})
</script>
1
2
3
4
5
6
7
8
<p v-big></p>

<script>
// 等于同时定义 bind、update 钩子函数
Vue.directives("big",function(element,binding){
element.innerText = binding.value * 10; //绑定元素内容增加10倍作为元素内容
})
</script>

实现原理


MVVM模型

  • MVVM模型
    1. M 模型(Model):对应data中的数据
    2. V 视图(View):模板
    3. VM 视图模型(ViewModel):Vue实例对象

生命周期-函数

生命周期:又名生命周期回调函数,生命周期函数,生命周期钩子
作用:Vue在特殊时刻调用的的特殊名称的函数
this:生命周期函数的 this 指向 Vue实例组件实例对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
var vm = new Vue({
el:"#root",
data:{
name:"xxx"
},
beforeCreate(){}, //初始化生命周期、事件之后
created(){}, //初始化数据监测、数据代理之后

beforeMount(){}, //生成虚拟DOM之后
mounted(){}, //虚拟DOM挂载到页面之后

beforeUpdate(){}, //修改数据之后
updated(){}, //修改数据并且渲染到页面后

beforeDestroy(){}, //调用销毁Vue实例函数,但在实际销毁Vue实例之前
destroyed(){} //实际销毁Vue实例之后

})
</script>

生命周期函数分类

  1. 初始化
    1. 生命周期、事件:beforeCreate()
      • 初始化Vue实例之后就打算执行(无法调用data中数据)
    2. 数据监测、数据代理:created()
      • 初始化Vue实例之后就打算执行(可以调用data中数据)
  2. 初始化页面
    1. 虚拟DOM:beforeMount()
      • 模板生成虚拟DOM之后就打算执行
    2. 渲染页面:mounted()
      • 将虚拟DOM转真实DOM渲染到页面就打算执行
  3. 修改数据
    1. 更新数据:beforeUpdate()
      • 数据更新为新数据,但页面还没渲染上新数据时调用
    2. 渲染页面:update()
      • 比较虚拟DOM,页面渲染了修改的新数据后调用
  4. 销毁Vue实例
    1. 准备销毁:beforeDestroy()
      • 调用销毁Vue实例函数,但是还没有实际销毁Vue实例
    2. 销毁完成:destroyed()
      • 实际销毁Vue实例之后调用

可用数据

模板语法的值

  • JS表达式
  • Vue实例 对象中的所有属性和方法(包括 $ _ )
    • 模板语法中直接使用Vue实例中的属性和方法,不需要使用Vue实例调用

Vue实例数据结构

  • $ 开头的属性和函数都是给开发人员使用的数据和函数
  • _ 开头的属性和函数是Vue内部使用的数据和函数,开发人员可以用但是不建议
  • 实例化Vue时,传入的data数据中的所有属性,都出现在Vue实例对象上

Vue直接调用data数据原理

通过数据代理方式,Vue实现了对data数据的调用


数据代理

使用 Object.defineProperty( ) 函数实现数据代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let number = 18
let person = {
name:"张三"
}

Object.definePerperty(person,"age",{
value:18, //设置属性值
enumerable:true, //设置属性是否可以枚举,默认false
writable:true, //设置是否可以被修改,默认false
configurable:true //设置是否可以被删除,默认false

//当读取或修改 age 属性时,就会调用 get set 函数,从而实时获取或修改作为属性的数据
get(){
return number
}
set(val){
number = val
}
})

Vue实现数据代理

  1. Vue实例中 _data 属性,就是实例化Vue时传入的 data 数据, _data 指向了 data vm._data === data
    • 虽然 vm._data === data ,但是在将 data 的值传递给 _data 之前进行了 数据劫持 , 将 data 中的数据通过 get()/set() 实现,然后将加工后的数据传递给 _data ,使得修改数据时能够进行监听,从而实时展示模板中的数据
  2. 使用 Object.defineProperty()函数 ,将 _data 数据中的每个属性通过 get()/set() 代理到 Vue实例
  3. 至此, Vue实例 就可以直接使用 data ( _data ) 中的数据,修改 Vue数据 就是修改 data ( _data ) 中的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 数据代理流程

var obj_a = {a:1}
var obj_b = {b:2}

Object.defineProperty(obj_b,"a",{
get(){
// obj_b 就可以读取 obj_a 的属性 a
return boj_a.a
}
set(val){
// obj_b 就可以设置 obj_a 的属性 a
obj_a.a = val
}
})

Vue监测数据改变原理

data 数据赋值给 _data(根数据对象) 之前,先将 data 数据中的属性都加工成了 get/set属性

因此修改数据时会调用set方法,就可以执行相关操作,监控数据的改变

不会触发数据监控的数据

即:Vue不会改造为get/set属性的数据

初始化渲染时,会将所有data中数据渲染到模板。但是因为部分类型数据没有被监视,所以后续对数据的修改,部分数据不能实时渲染到模板上

1. 不是在 data 中预定义的对象属性,而是在代码中通过Vue实例动态给 对象数据 新增的 属性(实例添加的对象属性)

1
2
3
4
5
6
7
8
9
10
var vm = new Vue({
el:"#root",
data:{
obj:{
name:"小明"
}
}
})

vm.obj.sex = "12" //通过Vue实例添加的此sex属性,不是get/set属性,无法被Vue监测

2. 数组元素(数组元素本身)

  1. 数组元素修改不能被监测。元素不是 get/set 数据
  2. 数组的元素是对象,其属性修改可以被监测。对象元素内属性是 get/set 数据
1
2
3
4
5
6
7
8
9
10
var vm = new Vue({
el:"#root",
data:{
arr:["小红","小刚","小兰"], //数组元素 "小红","小刚","小兰",不是get/set属性,无法被Vue监测
obj:{
name:"小明",
pengyou:["小红","小刚","小兰"] //数组元素 "小红","小刚","小兰",不是get/set属性,无法被Vue监测
}
}
})

解决方法

总结:

  • 数组的元素,永远不能是 get/set 形式,无法被监控(只针对数组元素本身,不针对元素的属性
  • 数组元素的添加修改,可以使用 set() 或 数组方法
  • 想通过 Vue 实例添加对象属性,使用 set() 添加,此属性可以被监测

方法1:Vue.set( )this.$set( )(vm.$set( )),添加( 对象数据属性 )或添加修改( 数组元素
Vue.delete( )this.$delete( )(vm.$delete( )),删除 ( 对象数据属性

不能添加修改 Vue实例上的属性数据,只能添加修改 Vue实例对象/数组属性属性或元素

  • 对象
    • 使用 set() 方法,可以添加 get/set 形式的对象数据属性 ,可以被Vue 数据监视
    • 如果添加的 属性值是数组 ,则此 数组本身 是 get/set 属性,但是 数组的元素 依旧不是 get/set ,不能被数据监控
    • 总结
      1. 通过 set() 添加的对象属性,修改时都会被监测到
      2. 通过 set() 添加的对象属性是数组,修改其元素不会被监测到,修改属性指向新数据可以被检测到
  • 数组
    • 使用 set() 方法,添加/修改元素,并不会将 数组元素 设置为 get/set,而是直接更改(添加/修改) 数组元素,并且主动执行Vue的监视和渲染功能
    • 如果修改或添加的 元素是对象此对象元素 不是 get/set , 依旧无法被监控,但是对象内部属性是 get/set 属性,可以被数据监控
    • 不使用 set() 方法,而使用 赋值方式 修改数组的对象数据类型元素,其属性依旧不能被Vue数据监控
  1. Vue.set()
    1. Vue.set(vm.obj,"name","小明") Vue.set(vm.arr,2,"小明")
    2. Vue类函数
    3. 参数
      1. Vue实例的对象/数组数据
      2. 此对象添加的 属性名
      3. 此对象添加的 属性值
  2. vm.$set()
    1. vm.$set(vm.obj,"name","小明") vm.$set(vm.arr,2,"小明")
    2. Vue实例方法
    3. 参数
      1. Vue实例的对象/数组数据
      2. 此对象添加的 属性名
      3. 此对象添加的 属性值

方法2:使用数组方法,添加/修改 数组元素

数组的方法 被重定义,调用相关方法操作数组有额外操作进行监视和渲染模板

  1. push
    • 数组的末尾添加一个或多个元素
    • 参数:一个或多个,添加到数组的元素
    • 返回值:新的长度
  2. pop
    • 删除数组的最后一个元素
    • 参数:无
    • 返回值:删除的元素
  3. shift
    • 数组的第一个元素从其中删除
    • 参数:无
    • 返回值:移除的元素
  4. unshift
    • 开头添加一个或更多元素
    • 参数:一个或多个,添加到数组的元素
    • 返回值:新的长度
  5. splice
    • 添加或删除数组中的元素
    • 参数
      1. 开始下标
      2. 删除元素个数
      3. 3,4,5…要添加的一个或多个元素
    • 返回值
    • 删除的元素的数组
  6. sort
    • 对数组的元素进行排序
    • 参数:方法
    • 返回值:对数组的引用,在原数组上进行排序,不生成副本
  7. reverse
    • 颠倒数组中元素的顺序
    • 参数:无
    • 返回值:对数组的引用,在原数组上进行排序,不生成副本

组件编程

组件定义:实现应用中 局部 功能 代码资源集合


Vue脚手架

vue脚手架即 Vue CLI(命令行接口工具)


初始化

  1. 全局安装
    • npm i @vue/cli -g
  2. 创建项目
    1. 进入创建项目的目录
    2. vue create xxx
  3. 启动项目
    • npm run serve

项目结构

  1. .gitignore 文件
    • git忽略文件,配置不想进行git管理的文件或目录
  2. babel.config.js 文件
    • babel配置文件 ES6转ES5
  3. package-lock.json 文件
    • 包版本控制文件,记录使用包的版本等信息
  4. package.json 文件
    • 包配置文件
  5. README.md 文件
    • 项目描述文件
  6. src 目录
    1. main.js 文件
      • 项目入口文件,运行指令 npm run serve 就执行此文件
    2. app.vue 文件
      • 汇总所有组件。所有组件的父组件
    3. assets 目录
      • 存放静态资源
    4. component 目录
      • 存放组件
  7. public 目录
    1. index.html 文件
      • 主页面
    2. favicon.ico 文件
      • 页面图标

render函数(模板解析器)

模板解析器用于生成模板

  1. 添加Vue实例的配置项 render
  2. render 配置项是函数
  3. Vue内部调用 render配置函数,并传入一个回调函数用于 创建节点
  4. render配置函数 的函数体中 调用回调函数 生成 VNode对象(vue节点对象)
  5. render配置函数 return 返回 VNode对象(vue节点对象)
1
2
3
4
5
6
7
8
9
10
11
12
13
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false // 关闭开发版本提示

new Vue({
// render: h => h(App), //简写

render(createElement){ //回调函数(生成节点)
var a = createElement(App); // 调用回调,生成vue节点
return a // 返回vue节点对象
}
}).$mount('#app')

Vue脚手架引入的Vue版本,是精简版本,此版本不包含 模板解析器,为了打包的项目精简

vue.js 和 vue.runtime.xxx.js 的区别

  1. vue.js是完整版的Vue,包含:核心功能+模板解析器
  2. vue.runtime.xxx.js 是运行版的Vue。只包含核心功能;没有模板解析器

修改默认配置

  • 基于 webpack 的 vue 配置
  1. 查看配置:使用命令 vue inspect > output.js ,根目录下会生成一个 output.js 文件,此文件就是默认配置。只能观看,修改无用
  2. 修改配置:根目录新建文件 vue.config.js,然后在此文件中可以对脚手架进行个性化配置。详情:https://cli.vuejs.org/zh/config/

编程方式

编程流程

  1. 拆分静态组件
    1. 组件要按功能拆分
    2. 命名不要与html元素冲突
  2. 实现动态组件
    1. 数据存放位置
      1. 一个组件用:放在组件自身
      2. 多个组件用:放在他们共同父组件上(状态提升)

添加css文件

  1. 方法一
    1. css文件放入 assets 文件夹中(可定义子文件夹)
    2. App.vue (或个别组件)文件中用 import 引入 import "./assets/css/xxx.css"
  2. 方法二
    1. public 文件夹中放入css文件(可定义子文件夹)
    2. index.html 文件中用 link 标签引入css样式 <link rel="stylesheet" href="<%= BASE_URL %>css/xxx.css">

组件的原理

组件本质是一个构造函数 VueComponent()构造函数


组件流程

  1. 组件的本质是一个 VueComponent()构造函数
  2. VueComponent()构造函数 是定义组件时由 Vue.extend() 类函数 创建并返回Vue.extend = function(){ return function VueComponent (){...} }
  3. Vue解析 组件标签 时(如<app></app>), 就会调用 VueComponent()构造函数 实例化 VueComponent实例对象 new VueComponent(options)
  4. 定义组件简写方式的流程

每次调用 Vue.extend(options),返回的都是新的 VueComponent()构造函数


this指向

  1. 组件配置中
    • data函数结构、methods中函数、watch中函数、computed中函数 this均是 【VueComponent实例对象】
  2. new Vue(options) 配置中
    • data函数结构、methods中函数、watch中函数、computed中函数 this均是 【Vue实例对象】

组件实例对象简称

VueComponent 组件实例对象 简称 vcVue实例对象 简称 vm


vm / vc 原型链

VueComponent.prototype.__proto__ === Vue.prototype

为了组件实例对象(vc)可以访问 Vue原型上的属性、方法

基础介绍

  • 显示原型对象
    • fn.prototype
    • 函数 通过属性 prototype 指向的对象。因为此属性是留给程序员进行操作的,所以称为 显示原型对象
  • 隐式原型对象
    • obj.__proto__
    • 对象 通过属性 proto 指向的对象。因为此属性是留给javascript底层自行查找调用的,所以称为 隐式原型对象。虽然程序员可以访问,但是不建议操作

组件的类型


非单文件组件

一个文件中有多个组件。.html 文件


组件使用步骤

  1. 定义组件(创建组件)
  2. 注册组件
  3. 使用组件(使用组件标签)

定义组件

组件使用 Vue.extend(options) 创建,返回的是 VueComponent()构造函数 (组件原理说明

optionsnew Vue(options) 中的 options 有区别

  1. 组件定义时,不能写 el 配置项
    • 所有组件都经过一个vm实例管理,由vm中的 el 配置项决定服务哪个容器
  2. data 必须使用函数式数据结构
    • 避免组件复用时,数据被共享
  3. 使用 template 配置组件结构
  4. 组件模板只能有一个根元素
    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
    var zj = Vue.extend({
    template:`
    <div>
    <p>{{name}}</p>
    </div>
    `,
    data(){
    return {
    name:"小明"
    }
    }
    })

    //定义组件的简写形式
    var zj2 = {
    template:`
    <div>
    <p>{{name}}</p>
    </div>
    `,
    data(){
    return {
    name:"小明"
    }
    }
    }

注册组件
  1. 组件需要在父组件或vm实例中注册
  2. 注册前需要先引入组件
  3. 注册的是VueComponent()构造函数
    组件原理说明
  1. 局部注册
    • new Vue({ components:{组件1:vc构造函数, 组件2:vc构造函数} })
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      var zj = Vue.extend({
      template:`
      <div>
      <p>组件内容</p>
      </div>
      `
      })

      new Vue({
      el:"#root",
      //局部注册
      components:{
      com1:zj
      }
      })
  2. 全局注册
    • Vue.component("组件名",vc构造函数)
    • 同页面多Vue实例都可以使用此组件
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      var zj = Vue.extend({
      template:`
      <div>
      <p>组件内容</p>
      </div>
      `
      })

      // 全局注册
      Vue.component("com2",zj)

使用组件

<组件名></组件名>

1
2
3
4
<div id="root">
<com1></com1>
<com2></com2>
</div>

注意事项


组件命名
  1. 一个单词
    1. 首字母小写:school
    2. 首字母大写:School
  2. 多个单词
    1. kebab-case命名:my-school
    2. CamelCase命名:MySchool(需要Vue脚手架支持)
  3. 组件名应避免HTML已有元素名

组件标签-调用

<school></school>
<school/>

不使用脚手架时,<school/> 会导致后续组件不能渲染


定义组件-简写

var school = Vue.extend(options) 可以简写为 var school = options

即使简写,Vue解析 组件标签 时(如<app></app>),依旧会调用 Vue.extend() 返回 VueComponent()构造函数 并进行组件的注册,并实例化 VueComponent对象

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
<div id="root">
<school></school>
</div>

//注册组件-常规写法
var school = Vue.extend({
template:`
<div> 组件内容 </div>
`
})
//注册组件-简写方法
var school = {
template:`
<div> 组件内容 </div>
`
}

//定义Vue实例
new Vue({
el:"#root",
components:{
school
}
})


组件嵌套

组件中可以嵌套注册其他组件

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
<div id="root">
<app></app>
</div>

var zj1 = Vue.extend({
template:`
<div>
<p>{{name}}</p>
</div>
`,
data(){
return {
name:"子组件内容"
}
}
})
var app = Vue.extend({
template:`
<div>
app组件内容
<nzj></nzj>
</div>
`,
components:{
nzj:zj1
}
})

new Vue({
el:"#root",
components:{
app:app
}
})

单文件组件

一个文件中只有一个组件。.vue 文件

单文件组件结构

  1. <template>
    1. 用来定义组件模板
    2. <template> 标签不参与解析
  2. <script>
    1. 生成VueComponent构造函数(生成组件构造函数)
    2. 暴露VueComponent构造函数(暴露组件构造函数)
    3. 生成、暴露语法可以简写
  3. <style>
    1. 定义组件样式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div>
{{name}}
</div>
</template>

<script>
var zj = Vue.extend({
name:"school",
data(){
return {
name:"组件内容"
}
}
})
export defult zj
</script>

<style>
div{
background-color:red;
}
</style>

单文件组件简写

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
// 1. 默认暴露
// 2. Vue.extend() 可以省略,解析组件标签时会默认调用 Vue.extend() 函数
export defult {
name:"school",
data(){
return {
name:"组件内容"
}
}
}
</script>


插槽

父组件调用子组件标签,动态给子组件模板指定的位置插入 HTML结构

  1. <slot>插槽 中可以定义 默认值 ,当没有给插入内容,则页面显示默认值
  2. <slot>插槽 中可以插入 多个 HTML结构,作用域插槽 除外
  3. 父组件插入的html结构,可以使用 <template>标签 组织结构,配置具名插槽可以使用 v-slot: 替换 slot属性 <template v-slot:name值> html结构 </template>

默认插槽

父组件调用子组件标签,定义子组件标签内容,内容插入到子组件模板 <slot>标签

  1. 定义插槽
    1. 子组件模板中定义 插槽标签 <slot></slot>
      • 父组件将HTML结构插入到子组件的位置
  2. 插入结构
    1. 父组件中调用 子组件标签
    2. 子组件标签 内容定义 html结构
1
2
3
4
5
6
7
8
9
10
11
12
//父组件中
<zizujian>
<div>html结构</div>
</zizujian>

//子组件中
<template>
<div>
<!-- 定义插槽 -->
<slot>插槽默认内容</slot>
</div>
</template>

具名插槽

父组件插入的HTML结构,到子组件 name属性 指定的 <slot>标签

  1. 定义插槽
    1. 子组件模板中定义 插槽标签 <slot></slot>
      • 父组件将HTML结构插入到子组件的位置
    2. <slot>标签 定义 name属性
  2. 插入结构
    1. 父组件中调用 子组件标签
    2. 子组件标签 内容定义 html结构
    3. html结构 添加属性 slot,属性值为 <slot>标签name值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//父组件中
<zizujian>
<template v-slot:aaa>
<div>html结构</div>
</template>
</zizujian>
<zizujian>
<div slot="bbb">html结构</div>
</zizujian>

//子组件中
<template>
<div>
<!-- 定义插槽 -->
<slot name="aaa">插槽默认内容1</slot>
<slot name="bbb">插槽默认内容2</slot>
</div>
</template>


作用域插槽

子组件中的数据交给父组件,父组件根据获取到的子组件数据 动态生成html结构

  1. 定义插槽
    1. 子组件模板中定义 插槽标签 <slot></slot>
      • 父组件将HTML结构插入到子组件的位置
    2. <slot>标签 添加 自定义属性
    3. 自定义属性v-bind 绑定,可用于传递不同类型数据
    4. 可以传递多个数据
    5. 可以定义 name属性
  2. 插入结构
    1. 父组件中调用 子组件标签
    2. 子组件标签 内容必须定义 <template>标签
    3. <template>标签 添加属性 scope,属性值为 随意定义标识符
      • scope属性值 为自定义名称,数据类型为对象,此对象属性为子组件 <slot>标签 上 v-bind 绑定的的所有属性 键值对
      • scope属性值 可以使用 解构赋值
      • slot-scope属性 等同于 scope属性,是最新语法
        • slot-scope属性 可以应用在 普通html标签 上接收数据
        • scope属性 只能应用在 <template>标签 上接收数据
    4. html结构 可以直接使用 scope属性值,生成 html结构 插入子组件模板
    5. 同一个 子组件标签 中定义多个html结构内容,只有最后一个生效
    6. 获取子组件数据的html结构和普通html结构并存,则获取子组件数据的html结构插入模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//父组件中
<zizujian>
<template scope="zidingyi"> //自定义名称
<div>获取数据插入子组件模板:{{ zidingyi.shuju }}</div>
</template>
</zizujian>
<zizujian>
<template slot-scope="{shuju, shuju2}"> //解构赋值
<div>获取数据插入子组件模板:{{ shuju2 }}</div>
</template>
</zizujian>

//子组件中
<template>
<div>
<!-- 定义插槽 -->
<slot name="aaa" :shuju="123456" :shuju2="2222">插槽默认内容1</slot>
</div>
</template>

属性-配置项


标签属性

ref:标签属性

用来给元素或子组件注册引用信息(id的替代者)
通过 Vue或父组件实例$refs属性 ,可以直接获取 DOM元素 或者 子组件实例

<zi ref="xxx">子组件标签</zi>
this[vm].$refs.xxx

  1. 应用在html标签上,获取的是真实DOM元素
  2. 应用在组件标签上,获取的组件实例对象(vc)
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
<div id="root">
<p ref="ys">html元素内容</p>
<school ref="zj" id="zjid"></school>
</div>

//定义school组件
var school = Vue.extend({
template:`
<div>
组件内容
</div>
`
})

//定义Vue实例
new Vue({
el:"#root",
components:{
school //注册组件
},
computed:{
ff(){
console.log( this.$refs.ys ) // 获取html标签DOM节点
console.log( this.$refs.zj ) // 获取组件实例对象
console.log( document.getElementById("zjid") ) // 获取组件生成的真实DOM节点,id会绑定到真实DOM最外层
}
}
})

style标签属性


scoped

让样式在局部生效,防止冲突
声明 scoped属性 后,style标签 中定义的样式只应用在当前组件的模板
样式也应用不到 子组件

如果<script>标签中没有定义 scoped 属性,多个组件引入到同一组件中,相同的样式的定义会发生冲突,最后引入的组件样式生效

1
2
3
<style scoped>

</style>

lang

用来定义声明样式的语言,可以是 css,也可以是预编译语言 less
声明了 lang 属性,必须指定值。否则不要声明 lang 属性,默认为 css 声明样式

1
2
3
<style lang="less">

</style>

Vue-类函数


mixin:混入

多个组件共享同一配置项的内容

  1. 组件配置项和混合配置项相同,以组件配置项为准
  2. 生命周期函数冲突,组件配置和混合配置的生命周期共存,先执行混合配置生命周期再执行组件配置生命周期

流程

  1. 定义混合
    1. 创建一个js文件
    2. 定义配置项
    3. 暴露配置项对象
      1
      2
      3
      4
      export const hunru = {
      data(){...},
      methods:{...}
      }
  2. 使用混合
    1. 全局混入:Vue.mixin(xxx)
      1. 打开 main.js
      2. 引入混合js模块
      3. 调用 Vue.mixin() 函数
        1
        2
        3
        4
        5
        import {hunru} from "../mixinhr.js" //引入混合模块
        import {hunru2} from "../mixinhr.js" //引入混合模块

        Vue.mixin(hunru) //配置混入
        Vue.mixin(hunru2) //配置混入
    2. 局部混入:mixins:["xxx"]
      1. 打开需要混入的组件
      2. 引入混合js模块
      3. 配置项添加 mixins 属性
        1
        2
        3
        4
        5
        6
        import {hunru} from "../mixinhr.js" //引入混合模块

        Vue.extend({
        template:`<div></div>`,
        mixins:[hunru] //配置混入
        })

use:插件

作用(用于增强Vue功能)

  1. 通过调用 Vue.use( ) 函数,给Vue添加额外的功能

特性

  1. Vue.use 会自动阻止多次注册相同插件
  2. 需要在调用 new Vue() 启动应用之前完成
  3. 参数为 ObjectFunction
    1. Object:必需要定义一个 install 方法
    2. Function:这个函数就被当做 install 方法

用法

  1. Vue.use() 参数
    1. 参数1:对象 ,用来设置功能
      • 此对象必须定义 install : function(){…} 函数
    2. 参数2-n:传入设置功能需要的参数,由 install 函数 2-n 形参接收
  2. install函数有两个参数
    1. 参数1:Vue构造函数
    2. 参数2-n:调用 Vue.use() 2-n 实参传入的参数
  3. 常用于在 main.js 文件中 实例化Vue 之前进行一些预处理,或增加一些功能
    1. 可以定义js模块
    2. 暴露 对象参数
    3. main.js 引入
    4. new Vue() 前执行 Vue.use()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Vue.use({
install(Vue,a,b){
// 1. 添加全局过滤器
Vue.filter(...)

// 2. 添加全局指令
Vue.directive(...)

// 3. 配置全局混入(混合)
Vue.mixin(...)

// 4. 添加实例方法
Vue.prototype.$myfangfa = function(){...}
}
})

实例-配置项


props:组件接收数据

用于让组件接收外部传入的数据

  1. props 是只读的(可以被修改但是会报错,修改对象值不会监测到报错)
  2. props配置项 接收的数据绑定在 vc实例

接收数据

  1. 只接收数据
    1
    props:["name","age"]
  2. 限制接收数据 类型
    1
    2
    3
    4
    props:{
    name:String, //显示类型
    age:Number //显示类型
    }
  3. 限制接收数据 类型 + 默认值 + 必须传入(可以不用全部配置)
    1
    2
    3
    4
    5
    6
    7
    props:{
    name:{
    type:String, //类型
    required:true, //必须传入
    default:'小红' //默认值
    }
    }

传入数据

  1. 通过定义 组件 标签属性 传入数据
  2. 默认传入的数据都是 字符串
  3. 通过 v-bind 绑定属性,使属性值为表达式,可以传入任意类型的数据
1
2
3
<div id="root">
<school name="小红" :age="17" sex="女"></school> <!-- 传入数据,v-bind 将传入数据转为表达式 -->
</div>

修改传入数据

  1. props接收的数据,优先于data中的数据
  2. props接收的数据 不能直接修改
    • 需要复制props数据到data中,然后修改data中数据
    • 接收的数据是对象,修改对象值不会被监测到所以不报错,但是依旧不建议修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Vue.extend({
templage:`
<div>
<p>{{age}}</p>
<button @click="myage++">按钮</button>` //修改复制到data中的数据
`</div>
`,
props:["age"],
data(){
return {
myage:this.age //data复制props中数据
}
}
})


name:组件别名

  1. 定义组件时配置项 name属性 ,用来修改浏览器中vue开发者工具呈现的组件名称
  2. 路由跳转时,组件别名 name,作为 <keep-alive> 标签的 include属性 的值,用来指定需要缓存的组件
  3. 组件中需要调用自身,递归组件
1
2
3
4
5
6
7
8
// 声明组件实例

export default {
name: "别名", // 组件别名
data(){
return {...}
}
}

activated:激活

  1. 特有生命周期函数
  2. 路由跳转的组件,所特有的实例配置项
  3. 当组件通过路由展示出来,则触发此特别生命周期函数
1
2
3
4
5
6
export default {
data(){...},
activated(){ // 路由组件激活生命周期函数
...
}
}

deactivated:失活

  1. 特有生命周期函数
  2. 路由跳转的组件,所特有的实例配置项
  3. 当组件因为路由跳转被缓存不显示,则触发此特别生命周期函数
1
2
3
4
5
6
export default {
data(){...},
deactivated(){ // 路由组件失活生命周期函数
...
}
}

实例-属性(方法)


$on:绑定自定义事件

用于给 组件实例 绑定自定义事件
(跳转详细介绍)


$emit:触发自定义事件

用于触发 组件实例 上绑定的自定义事件
(跳转详细介绍)


$nextTick:执行时机

  1. 特有生命周期函数
  2. 用于修改数据渲染页面之前,修改DOM节点

问题原因

Vue不是在数据进行改变就立即解析模板,而是在虚拟DOM渲染到页面后才执行 update() 生命周期函数 (生命周期) ,所以在此之前需要对最新DOM节点的修改并不会奏效

用法

Vue实例的 $nextTick(回调函数) 方法,是在 下一次DOM更新之后执行指定回调函数

1
2
3
4
this.$nextTick(function(){
// 修改数据后,数据也渲染到页面后,执行此函数
console.log("页面渲染修改数据后,执行此函数")
})

数据传递


父子

父子间数据传递


父 -> 子

  1. 父组件中调用子组件标签
  2. 子组件标签添加自定义属性
  3. v-bind 绑定属性,可以传递任意类型数据,否则只能传递字符串
  4. 子组件中通过 props 属性接收数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var zi = Vue.extend({
template:"<div>{{shuju}}</div>", //子组件使用接收的数据
props:["shuju"] //子组件接收数据
})

var fu = Vue.extend({
template:`
<div>
<zi shuju="123"></zi>` // 父组件向子组件传递数据
`</div>
`,
components:{zi}
})


子 -> 父

props传递函数
  1. 父组件中调用子组件标签
  2. 子组件标签添加数据属性
  3. 父组件数据属性通过 v-bind 绑定(作用是为了可以传递任意类型数据)
  4. 父组件数据属性值为 mathods 定义的 函数(接收参数,通过this将参数赋值给data定义的数据)
  5. 子组件中通过 props 属性接收函数
  6. 子组件中调用 接收函数 ,修改父组件数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var zi = Vue.extend({
template:"<div><button @click="ccff(456)">修改父组件数据</button></div>", //子组件调用接收函数修改父组件数据(456)
props:["ccff"] //子组件接收函数
})

var fu = Vue.extend({
template:`
<div>
<zi :shuju="ccff"></zi>` // 父组件向子组件传递函数
`</div>
`,
components:{zi},
data(){
return {
fshuju:"123" //父组件定义的数据(123)
}
},
methods:{
ccff(x){ //定义函数
this.fshuju = x;
}
}
})


自定义事件

自定义事件是应用在组件上的,适用于 子组件 —> 父组件 传递数据
组件绑定事件,即使绑定内置事件,Vue也默认为绑定的是 自定义事件

绑定

使用方式

  1. 父组件代码中:
    1. 父组件代码中给 子组件实例 绑定 自定义事件
      • 使用 v-on子组件标签 绑定 自定义名称的事件(通过标签绑定自定义事件)
      • 使用 $on子组件实例 绑定 自定义名称的事件(通过代码绑定自定义事件)
    2. 赋值一个 事件处理函数用于接收数据
      1. 事件处理函数不用带括号
      2. 必须定义形参,用于接收数据
  2. 子组件代码中:
    1. 子组件实例 调用 vc.$emit() 触发 自定义事件用于发送数据,并 执行事件处理函数

使用原理

  1. 获取 子组件实例
  2. 子组件实例 上绑定 自定义事件
  3. 子组件实例 调用 $emit() 函数,触发事件

特点

  1. 绑定自定事件,是为子组件实例 vc 身上绑定自定义事件
  2. 组件绑定事件,即使绑定内置事件,Vue也默认为绑定的是 自定义事件
    1. 想要使用原生事件:绑定事件添加 .native 事件修饰符
  3. 触发事件:
    1. vc.$emit()
    2. 触发绑定到组件实例 vc 身上的事件
    3. 参数
      1. 参数1:声明的自定义事件(String)
      2. 参数2-n:传递给事件处理函数的多个参数
  4. 绑定方式:
    1. v-on组件标签 上进行绑定
    2. 组件实例vm 绑定
      1. 依旧需要先调用 子组件标签
      2. 子组件标签绑定 ref 属性
      3. vm.$refs.xxx 获取到子组件实例 vm
      4. 调用 $on() 方法绑定事件
        1. 参数1:自定义的事件名称
        2. 参数2:声明的事件处理函数
    3. 只触发一次
      1. v-on:组件标签添加 .once 修饰符
      2. $once:使用 $once() 方法替换 $on()
  5. 事件处理函数:
    1. 绑定时传入的事件处理函数,不需要加括号( ),触发自定义事件时,事件处理函数形参依旧可以接收参数
    2. this
      1. 如果使用 $on 绑定
        1. 第二个参数定义为 匿名函数,则 this 指向 子组件实例对象
          • $on 回调函数的 this 由调用处决定(由子组件调用)
        2. 第二个参数定义为 methods 中定义的函数,this 指向 父组件实例对象
          • methods 中定义的函数,this 指向 当前组件实例
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
var zi = Vue.extend({
template:`
<div>
<button @click="ff">触发事件</button>` //当点击时触发ff函数
`</div>
`,
methods:{
ff(){
this.$emit("zdyshijian",111,222) //调用ff函数时,触发绑定在组件实例vc上的自定义事件
}
}
})

var fu = Vue.extend({
template:`
<div>
<zi @zdyzujian="sjcl" ref="zizujian"></zi>` // 绑定自定义事件方式1:事件处理函数不需要小括号()
`</div>
`,
components:{
zi
},
mounted(){
this.$refs.zizujian.$on("zdyzujian", this.sjcl) // 绑定自定义事件方式2:事件处理函数不需要小括号()
},
methods:{
sjcl(v1,v2){ // 接收触发自定义事件,传递的数据
console.log("输出接收数据:", v1, v2)
}
}
})

解绑

子组件中调用 vc.$off,即可解除 子组件实例 vc 上绑定的自定义事件

  1. 解绑 一个 自定义事件
    • vc.$off("自定义事件1")
  2. 解绑 多个 自定义事件
    • vc.$off([ "自定义事件1", "自定义事件2" ])
  3. 解绑 所有 自定义事件
    • vc.$off()

兄弟


任意传递


全局事件总线

使用 自定义事件 方式给一个 公用组件 绑定事件进行数据的传递

实现逻辑

  1. 打开main.js文件
  2. 创建共享vc实例
    • 调用 Vue.extend() 函数返回的是 VueComponent构造函数,需要 new 返回值,获取 vc实例
  3. vm 生命周期函数 beforeCreate ,给 Vue 原型对象上绑定属性,属性为此 vc 实例
  4. 接收数据组件:获取共享 vc 实例,调用 $on 函数,绑定自定义事件
  5. 传递数据组件:获取共享 vc 实例,调用 $emit 函数,触发自定义事件

注意事项

  1. 创建共享vc实例
    1. 可以省略创建共享vc实例,将Vue实例 vm 绑定到 Vue原型对象 作为其属性,供所有组件调用
    2. 依据 vc / vm 原型链规则
  2. 最好在 beforeDestroy 生命周期函数中,用 $off 解绑当前组件绑定的 自定义事件
  3. 全局事件总线属性名,常定义为 $bus

创建全局事件总线

1
2
3
4
5
6
7
8
9
// main.js 文件中

new Vue({
......
beforeCreate(){
Vue.prototype.$bus = this // 自定义属性 $bus ,绑定自定义事件实例为当前 Vue 实例
},
......
})

使用全局事件总线

1
2
3
4
5
6
7
8
9
10
11
12
13
// 绑定自定义事件的组件
methods:{
demo(data){....}
}
......
mounted(){
this.$bus.$on("xxx",this.demo)
}

//-------------------------------------

// 传递数据的组件
this.$bus.$emit("xxx", 数据)

消息订阅与发布(其他库)

使用第三方库实现数据的任意传递,其逻辑与 全局事件总线 相似,只是不是用的 共享组件
pubsub-js 第三方库

  1. 安装第三方库 npm i pubsub-js -S
  2. 引入第三方库 import pubsub from "pubsub-js"
  3. 接收数据(订阅消息)
    • 使用 pubsub.subscribe() 订阅消息
    • 接收数据的回调函数
      • 参数
        • 参数1:订阅的消息名(xxx)
        • 参数2-n:传递的多个数据
      • this
        • 自定义匿名函数:thisundefined
        • methods 定义函数:this组件实例vc
        • 箭头函数:this组件实例vc
          1
          2
          3
          4
          5
          6
          7
          methods:{
          dame(date){...} //接收数据
          }
          ......
          mounted(){
          this.pid = pubsub.subscribe("xxx",this.demo) //订阅消息
          }
  4. 发送数据
    1
    pubsub.publish("xxx",数据)  //发送数据
  5. 取消订阅
    • 最好在 deforeDestroy 生命周期函数中,用 pubsub.unsubscribe(pid) 取消订阅
    • pid 为订阅消息时的返回值,此值可以绑定在 vc实例 上,方便在钩子函数中接收
      1
      pubsub.unsubscribe(this.pid)

过渡-动画

在插入、更新、移除 DOM元素时,Vue 自动 给元素添加样式类名

原理

  1. Vue预定义标签:<transition></transition>
  2. Vue预定义类名:.v-enter、.v-enter-active、.v-enter-to、.v-eave、.v-leave-active、.v-leave-to
  3. 在Vue预定义的标签和类名中添加元素和样式,即可自动给元素在必要时添加移除类名

用法

  • 过渡
    • v-enter-activev-leave-active 预定义类中,用于设置过渡效果
  • 动画
    • 只需要配置 v-enter-activev-leave-active 预定义类的样式即可

<transition> 说明

  1. 只能过度一个元素(只能在<transition>中定义一个子元素)
  2. name 属性
    • 用于和样式类名关联
    • 预定义类名前的 v- 改为name属性值 value-
  3. appear 属性
    • 用于初始化页面触发过渡或动画
    • 直接添加属性即可,不用赋值

<transition-group> 说明

  • 可以过渡多个元素(<transition-group> 中可以定义多个子元素)

类名说明

  • 元素进入的样式:
    1. v-enter:进入的起点
    2. v-enter-active:进入过程中
    3. v-enter-to:进入的终点
  • 元素离开的样式:
    1. v-leave:离开的起点
    2. v-leave-active:离开过程中
    3. v-leave-to:离开的终点

第三方动画库

  1. animate.css
  2. 安装
  3. 引入
  4. <transition> 标签中的 name 属性值设置为样式库的 类名 animate__animated animate__bounce
  5. <transition> 标签中添加 进入属性 enter-active-class,值为所选进入样式的 类名
  6. <transition> 标签中添加 离开属性 leave-active-class,值为所选离开样式的 类名
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
<transition name="ys">
<div>添加样式的元素</div>
</transition>

<transition
name="animate__animated animate__bounce"
enter-active-class="xxxx"
leave-active-class="xxxx"
>
<div>第三方库样式</div>
</transition>

<script>
import "animate.css" //引入第三方库
</script>

<style>
.ys-enter{...},
.ys-enter-active{...},
.ys-enter-to{...},

.ys-leave{...},
.ys-leave-active{...},
.ys-leave-to{...}
</style>

ajax请求

前端跨域请求,请求数据已经发送到了服务器,服务器也接收到了请求,并返回了数据,但是因为同源策略,浏览器不返回结果

发送请求的方式

  1. xhr
    • javascript原生 new XMLHttpRequest()
  2. jQuery
    • 封装了 xhr
    • Vue中不推荐用
  3. axios
    • 封装了 xhr
    • promise 风格
    • 体积小
    • Vue中推荐使用
  4. vue-resource
  5. fetch
    • 独立的请求方式,不依赖 xhr
    • 返回数据包了两层 promise
    • 兼容不好IE不适用
    • Vue中不推荐使用

跨域请求的方式

  1. cors
    • 服务端修改相应数据的响应头,使浏览器支持跨域请求
  2. jsonp
    • script标签src属性引入外部文件不受同源策略限制
    • 只能解决 get 请求
  3. 代理服务器
    • 服务器和服务器之间的请求,不受同源策略限制
    1. 创建同域代理服务器
    2. 浏览器向代理服务器发送请求(同域请求不跨域)
    3. 代理服务器向目标服务器发送请求
    4. 代理服务器接收响应,并返回给浏览器

vue-resource

封装了ajax xhr代码,功能与 axios 相同
Vue 1.0版本使用的多,现官方已不再维护,不推荐使用
此为Vue插件库,需要通过 Vue.use() 添加此插件
添加此插件后 vm / vc 实例上就有了一个 $http 属性,用于实现ajax请求功能

  1. 安装vue-resource包
    • npm i vue-resource -S
  2. 打开main.js文件
  3. 引入 vue-resource
    • import vr from "vue-resource"
  4. 添加插件
    • Vue.use(vr)
  5. 调用请求
    • this.$http.get(...)
    • this.$http.post(...)
    • 使用方法与 axios 相同

代理服务器

  • 服务器和服务器之间的请求,不受同源策略限制
  1. 创建同域代理服务器
  2. 浏览器向代理服务器发送请求(同域请求不跨域)
  3. 代理服务器向目标服务器发送请求
  4. 代理服务器接收响应,并返回给浏览器

开启代理服务器方式

  1. nginx
  2. Vue-cli
    1. 开启代理服务器
    2. 配置目标服务器 域名、IP-端口
    3. ajax向代理服务器 域名、IP-端口 发送 请求地址

Vue配置方式一

配置方式

  1. 打开根目录下 vue.config.js 配置文件(没有的话创建)
  2. 添加 devServer 配置项
    • 配置目标服务器 域名、IP-端口
  3. 重启服务器 npm run serve
  4. ajax 请求地址的 域名、IP-端口,改为项目所在服务器 域名、IP-端口

注意事项

  1. 代理服务器和目标服务器有相同响应处理,则优先执行代理服务器中的响应,不再向目标服务器发送请求
  2. 只能添加一个代理,不能添加多个代理
1
2
3
4
5
6
7
8
9
10
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,

//开启代理服务器
devServer: {
proxy: 'http://mubiaofuwuqi:5000' //配置需要跨域请求的目标服务器 IP端口
}

})
1
2
3
4
5
6
7
8
9
//请求地址的 域名、IP-端口 为项目所在服务器的 域名、IP-端口
axios.get("https://localhost:8080/students").then(
response => {
console.log("请求成功")
},
error => {
console.log("请求失败")
}
)

Vue配置方式二

配置方式

  1. 打开根目录下 vue.config.js 配置文件(没有的话创建)
  2. 添加 devServer 配置项
    • 配置目标服务器 域名、IP-端口
  3. 重启服务器 npm run serve
  4. ajax 请求地址的 域名、IP-端口,改为项目所在服务器 域名、IP-端口(同域代理服务器)
    • 需要添加 请求前缀

注意事项

  1. 可以定义多个代理
  2. 代理需配置请求前缀,匹配以请求前缀开头相同的请求路径
  3. ajax请求路径也需要配置请求前缀,请求前缀紧跟在端口号后,后面路径保持不变
  4. 需要添加 pathRewrite 配置项,修改代理服务器请求目标服务器时请求路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,

//开启代理服务器
devServer: {
proxy: {
'/api': { // 请求前缀:匹配以 /xxx 开头的请求路径
target: 'http://mubiaofuwuqi:5000', // 配置需要跨域请求的目标服务器 IP端口
pathRewrite:{"^/api":""}, // 修改代理服务器请求目标服务器的地址(去掉请求前缀)
ws: true, // 用于支持 websocket
changeOrigin: true // 用于控制请求头中的host值(使目标服务器认为同域)
},
'/foo': {
target: 'http://mubiaofuwuqi:5000'
}
}
}

})
1
2
3
4
5
6
7
8
9
10
// 请求地址的 域名、IP-端口 为项目所在服务器的 域名、IP-端口
// 添加请求前缀 /api
axios.get("https://localhost:8080/api/students").then(
response => {
console.log("请求成功")
},
error => {
console.log("请求失败")
}
)

vuex

  1. Vue中实现集中式状态(数据)管理的一个 Vue插件
  2. 对Vue应用中多个组件的共享状态 (数据) 进行 集中式的管理(读/写)
  3. 也是组件间的通信方式,且适合任意 组件间通信

github地址:https://github.com/vuejs/vuex
新的存储库使用pinia:https://pinia.web3doc.top/


配置方式

vue2,只能用vuex3版本
vue3,只能用vuex4版本(不写版本默认为vue3专用)

  1. 创建store模块
  1. 安装vuex
    • npm i vuex@3 -S
  2. 根目录新建 store目录
  3. store目录创建 index.js文件
  1. 暴露store实例
  1. 打开 store 模块
  2. 引入 vue 模块
    • import Vue from 'vue'
  3. 引入 vuex 模块
    • import Vuex from 'vuex'
  4. Vue 添加 vuex 插件
    • Vue.use(Vuex)
  5. 配置并实例化 store 对象
    1. 配置:actions:{ }
    2. 配置:mutations:{ }
    3. 配置:state:{ }
    4. 配置:getters:{ }
  6. 暴露 store 实例
    1
    2
    3
    4
    5
    6
    export default new Vuex.Store({
    actions:{...},
    mutations:{...},
    state:{...},
    getters:{...}
    })
  1. Vue实例配置store属性
  1. 打开 main.js 文件
  2. 引入 store 模块
  3. Vue实例 配置 store属性
    1
    2
    3
    4
    5
    6
    import store from './store'

    new Vue({
    ...
    store //配置store实例
    })

运行流程

修改数据有两种流程

  1. 组件 ——> 数据处理函数 ——> 数据修改函数
  2. 组件 ——> 数据修改函数
1
2
3
4
5
6
7
8
9
10
<!-- 组件使用数据 -->
<!-- $store 对象在 Vue 配置项中配置了 store 后自动生成 -->

<zujian>
{{ $store.state.xxx }} <!-- 组件获取数据 -->
</zujian>

<zujian>
{{ $store.getters.xxx }} <!-- 组件获取加工数据 -->
</zujian>
1
2
3
4
5
6
7
8
9
10
11
12
// 组件使用数据
// $store 对象在 Vue 配置项中配置了 store 后自动生成

export default {
...
methods:{
ff(){
this.$store.dispatch("shuju1",123) // 组件调用数据处理函数——修改数据
this.$store.commit("SHU",123) // 组件调用数据修改函数——直接修改数据
}
}
}
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
// 配置 vuex
// 新建 store 模块

import Vue from "vue" //引入vue
import Vuex from "vuex" //引入vuex

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

export default new Vuex.Store({ // 创建并暴露 store 实例
actions:{
shuju1(par1_mini_store,par2){ // 创建数据处理函数
... //对数据其他加工处理
par1_mini_store.commit("SHU",par2) // 调用数据修改函数
}
},
mutations:{
SHU(par1_state,par2){ // 定义数据修改函数
par1_state.age = par2 // 修改数据
}
},
state:{
age:111 // 定义数据
},
getters:{
bigage(state){ //定义数据加工函数
return state.age * 10 // 返回加工数据
}
}
})


基础实现


store 对象

store 对象由来

Vue中添加了Vuex插件,并配置了store配置项,则Vue实例(vm)和组件实例(vc)中都将添加一个新属性 $store,指向 store 实例对象

store 对象作用

对数据的修改和读取,都基于 store 对象,需要调用 store 中对应方法和属性

store 对象 的属性如下:


dispatch : 方法

作用

调用 actions 中定义的函数(数据处理函数),修改数据前对数据进行额外操作

案例

1
store.dispatch("数据处理函数名",数据, 数据, ...)

用法

  • 调用者
    • store对象
  • 参数
    • 1:数据处理函数名(actions 中定义的函数名)
    • 2-n:数据

commit : 方法

作用

调用 mutations 中定义的函数(数据修改函数),对 state 保存的数据进行修改

案例

1
store.commit("数据修改函数名",数据, 数据, ...)

用法

  • 调用者
    • store对象
  • 参数
    • 1:数据修改函数名(mutations 中定义的函数名)
    • 2-n:数据

getters : 对象

作用

调用 getters 中定义的 getter(数据加工函数),获取对 state 进行加功处理的数据

案例

1
var bigshuju = store.getters.bigxxx

strict : 布尔值

state : 对象

作用:

  1. 用于获取数据
  2. 用于修改数据(建议在数据修改函数中修改)

本质

进行了数据劫持的 state配置项 ,属性是 getter/setter

获取数据

1
var shuju = store.state.xxx

修改数据

  1. 数据修改函数 的函数体中修改
  2. 组件实例直接调用 state属性 修改数据
    1. Vue开发者工具将无法获取到操作步骤
    2. 无法添加公用数据相关处理
1
store.state.xxx = yyy

store 配置


actions

作用

定义 数据处理函数

数据处理函数

数据修改前进行额外操作

  • 参数

    参数1:简化的 store对象
    参数2-n:调用 数据处理函数 时传入的数据

  • 修改数据

    函数体中调用 数据修改函数

    函数体中,参数1 store对象 调用 commit方法
    par1_mini_store.commit("数据修改函数名", 数据)

  • 增加处理功能

    函数体中也可以调用其他 数据处理函数

    函数体中,参数1 store对象 调用 dispatch方法
    par1_mini_store.dispatch("数据处理函数名", 数据)


mutations

作用

定义 数据修改函数

数据修改函数

主要在函数体中进行数据的修改

  • 参数

    参数1:对 state配置项 进行了数据劫持的 state对象 ,此对象的属性都是 getter/setter
    参数2-n:调用 数据修改函数 时传入的参数

  • 数据变更
    • 函数体变更

      数据修改函数 的函数体中进行数据的修改

      函数体中,参数1 state对象 直接调用数据进行修改
      par1_state.xxx = yyy

    • 组件变更

      组件实例通过 $store属性,调用 state属性,访问数据进行修改
      vc.$store.state.xxx = yyy

      问题:

      1. Vue开发者工具将无法获取到操作步骤
      2. 无法添加公用数据相关处理

state

作用

定义 数据


getters

作用

定义 数据加工函数

数据加工函数

state 中定义的数据进行额外加工(等同于Vue的计算属性)

  • 函数名

    可以自定义任意名称

  • 参数

    参数1:对 state配置项 进行了数据劫持的 state对象 ,此对象的属性都是 getter/setter

  • return
    1. 必须有返回值
    2. 返回值为加工了 state 中数据的返回值
  • 1
    2
    3
    4
    5
    getters:{
    chuli(state){
    return state.xxx * 10
    }
    }

简化读取

调用vuex模块中暴露的相关方法,便捷的读取共享数据


mapState

作用

便捷读取 state 中定义的数据

用法

  1. 引入函数
    • import { mapState } from 'vuex'
  2. 组件 计算属性配置项 computed 中调用
    • 调用并用ES6语法…展开
    • 实参
      1. 对象参数
        1. 属性:组件中获取数据时调用的名称
        2. 值:需要获取 state 中的数据名
      • 1
        2
        3
        computed : {
        ...mapState({ff1:"sum", ff2:"school"})
        }
      1. 数组参数
        • 元素:组件中获取数据时调用的名称 === 获取 state 中的数据名
      • 1
        2
        3
        computed : {
        ...mapState(["sum", "school"])
        }
  3. 调用数据
    • 组件中直接调用 对象属性名数组元素值
      1
      2
      3
      4
      5
      <zizujian>
      {{ ff1 }} <!-- 属性 -->
      {{ ff2 }} <!-- 属性 -->
      {{ sum }} <!-- 元素 -->
      </zizujian>

原理

  1. mapState函数 根据参数(对象属性/数组元素),生成多个函数
    1. 函数名
      1. 对象参数:属性名
      2. 数组参数:元素值
    2. 函数体
      1. 通过组件实例的 $store属性,获取 state,根据 属性值/元素值 获取数据,并 return 返回
    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      // 对象参数生成的函数
      ff1(){
      return this.$store.state.sum //sum 即为 【对象参数的属性值】
      }

      // 数组参数生成的函数
      sum(){
      return this.$store.state.sum //sum 即为 【数组参数的元素名】
      }
  2. 生成的函数作为整体对象返回,在组件的 计算属性 配置项使用ES6语法展开,生成函数即可作为组件的计算属性直接调用

mapGetters

作用

便捷读取 getters 中定义的加工数据

用法

  1. 引入函数
    • import { mapGetters } from 'vuex'
  2. 组件 计算属性配置项 computed 中调用
    • 调用并用ES6语法…展开
    • 实参
      1. 对象参数
        1. 属性:组件中获取数据时调用的名称
        2. 值:需要获取 getters 中的数据名
      • 1
        2
        3
        computed : {
        ...mapGetters({ff1:"sum", ff2:"school"})
        }
      1. 数组参数
        • 元素:组件中获取数据时调用的名称 === 获取 getters 中的数据名
      • 1
        2
        3
        computed : {
        ...mapGetters(["sum", "school"])
        }
  3. 调用数据
    • 组件中直接调用 对象属性名数组元素值
      1
      2
      3
      4
      5
      <zizujian>
      {{ ff1 }} <!-- 属性 -->
      {{ ff2 }} <!-- 属性 -->
      {{ sum }} <!-- 元素 -->
      </zizujian>

原理

  1. mapGetters函数 根据参数(对象属性/数组元素),生成多个函数
    1. 函数名
      1. 对象参数:属性名
      2. 数组参数:元素值
    2. 函数体
      1. 通过组件实例的 $store属性,获取 getters,根据 属性值/元素值 获取数据,并 return 返回
    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      // 对象参数生成的函数
      ff1(){
      return this.$store.getters.sum //sum 即为 【对象参数的属性值】
      }

      // 数组参数生成的函数
      sum(){
      return this.$store.getters.sum //sum 即为 【数组参数的元素名】
      }
  2. 生成的函数作为整体对象返回,在组件的 计算属性 配置项使用ES6语法展开,生成函数即可作为组件的计算属性直接调用

简化修改

调用vuex模块中暴露的相关方法,便捷的修改共享数据


mapActions

作用

便捷调用 actions 中定义的函数(数据处理函数)

用法

  1. 引入函数
    • import { mapActions } from 'vuex'
  2. 组件 函数配置项 methods 中调用
    • 调用并用ES6语法…展开
    • 实参
      1. 对象参数
        1. 属性:组件中修改数据时调用的函数名
        2. 值:需要调用 actions 中定义的函数名
      • 1
        2
        3
        methods : {
        ...mapActions({ff1:"jia", ff2:"jian"})
        }
      1. 数组参数
        • 元素:组件中修改数据时调用的函数名 === 调用 actions 中定义的函数名
      • 1
        2
        3
        methods : {
        ...mapActions(["jia", "jian"])
        }
  3. 调用数据
    • 组件中直接调用 对象属性名数组元素值
    • 调用生成函数,必须带小括号( ),并且传入需要修改的参数
      1
      2
      3
      4
      5
      <zizujian>
      {{ ff1(n) }} <!-- 属性 -->
      {{ ff2(12) }} <!-- 属性 -->
      {{ jia(n) }} <!-- 元素 -->
      </zizujian>

原理

  1. mapActions函数 根据参数(对象属性/数组元素),生成多个函数
    1. 函数名
      1. 对象参数:属性名
      2. 数组参数:元素值
    2. 参数
      • 形参1:传入需要修改的数据
      • 只能定义一个形参
    3. 函数体
      1. 通过组件实例的 $store属性,调用 dispatch函数
        1. 参数1:根据 属性值/元素值 调用 actions 定义的相关函数
        2. 参数2:生成的函数的 形参1。即 actions 定义的相关函数,需要传入的数据
    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      // 对象参数生成的函数
      ff1(par){
      return this.$store.dispatch("jia", par) //jia:【对象参数的属性值】—— par:【生成函数的形参】
      }

      // 数组参数生成的函数
      jia(par){
      return this.$store.dispatch("jia", par) //jia:【数组参数的元素名】—— par:【生成函数的形参】
      }
  2. 生成的函数作为整体对象返回,在组件的 函数声明 配置项使用ES6语法展开,生成函数即可作为组件的自定义函数直接使用

mapMutations

作用

便捷调用 mutations 中定义的函数(数据修改函数)

用法

  1. 引入函数
    • import { mapMutations } from 'vuex'
  2. 组件 函数配置项 methods 中调用
    • 调用并用ES6语法…展开
    • 实参
      1. 对象参数
        1. 属性:组件中修改数据时调用的函数名
        2. 值:需要调用 mutations 中定义的函数名
      • 1
        2
        3
        methods : {
        ...mapMutations({ff1:"JIA", ff2:"JIAN"})
        }
      1. 数组参数
        • 元素:组件中修改数据时调用的函数名 === 调用 mutations 中定义的函数名
      • 1
        2
        3
        methods : {
        ...mapMutations(["JIA", "JIAN"])
        }
  3. 调用数据
    • 组件中直接调用 对象属性名数组元素值
    • 调用生成函数,必须带小括号( ),并且传入需要修改的参数
      1
      2
      3
      4
      5
      <zizujian>
      {{ ff1(n) }} <!-- 属性 -->
      {{ ff2(12) }} <!-- 属性 -->
      {{ JIA(n) }} <!-- 元素 -->
      </zizujian>

原理

  1. mapMutations函数 根据参数(对象属性/数组元素),生成多个函数
    1. 函数名
      1. 对象参数:属性名
      2. 数组参数:元素值
    2. 参数
      • 形参1:传入需要修改的数据
      • 只能定义一个形参
    3. 函数体
      1. 通过组件实例的 $store属性,调用 commit函数
        1. 参数1:根据 属性值/元素值 调用 mutations 定义的相关函数
        2. 参数2:生成的函数的 形参1。即 mutations 定义的相关函数,需要传入的数据
    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      // 对象参数生成的函数
      ff1(par){
      return this.$store.dispatch("JIA", par) //JIA:【对象参数的属性值】—— par:【生成函数的形参】
      }

      // 数组参数生成的函数
      JIA(par){
      return this.$store.dispatch("JIA", par) //JIA:【数组参数的元素名】—— par:【生成函数的形参】
      }
  2. 生成的函数作为整体对象返回,在组件的 函数声明 配置项使用ES6语法展开,生成函数即可作为组件的自定义函数直接使用

模块化+命名空间

作用

让代码更好维护,多种数据可以分类管理

说明

模块化:创建不同文件,各自配置 store实例 中需要的相关配置项,然后暴露出来

命名空间:store目录index.js 文件引入各配置文件,并为其定义命名空间名称

配置文件

新建配置文件

  1. 新建独立js文件
  2. 暴露对象数据,即 new vuex.Store({}) 传入的配置对象
  3. 定义 namespaced:true 属性
1
2
3
4
5
6
7
export default {
namespaced:true, //开启命名空间
state:{x:1},
mutations:{...},
actions:{...},
getters:{...}
}

引入配置文件

  1. store目录 下的 index.js文件 中引入配置模块
  2. new Vuex.Store({...}) 配置项添加 modules 对象属性
  3. modules 中为配置数据定义命名空间
1
2
3
4
5
6
7
import pzx from "./pzx.js"

export default new Vuex.Store({
modules:{
nsp1 : pzx // 命名空间名称为 nsp1
}
})

调用

读取 state 数据

1
2
3
4
5
//方式一:直接读取数据
this.$store.state.命名空间.state数据

//方式二:借助 mapState 读取数据
...mapState("命名空间",["state数据1", "state数据2"])

读取 getters 数据

1
2
3
4
5
//方式一:直接读取数据
this.$store.getters["命名空间/getters计算属性"]

//方式二:借助 mapGetters 读取
...mapGetters("命名空间",["getters计算属性"])

使用 dispatch函数 调用 actions 定义的数据处理函数

1
2
3
4
5
//方式一:直接调用 dispatch 修改
this.$store.dispatch("命名空间/actions函数名", 传入的数据)

//方式二:借助 mapAction 修改
...mapAction("命名空间",{自定义组件调用函数名 : "actions函数名"})

使用 commit函数 调用 mutations 定义的数据处理函数

1
2
3
4
5
//方式一:直接调用 commit 修改
this.$store.commit("命名空间/mutations函数名", 传入的数据)

//方式二:借助 mapMutations 修改
...mapMutations("命名空间", {自定义组件调用函数名 : "mutations函数名"})

路由


路由说明

什么是路由

  1. 一个路由就是一组映射关系(key - value)
  2. key 为路径, value 可能是 function 或 componen
  3. 路由器:是对多个路由的管理

路由分类

  1. 前端路由:
    1. 理解:value 是 component,用于展示页面内容。
    2. 工作过程:当浏览器的路径改变时, 对应的组件就会显示。
  2. 后端路由:
    1. 理解:value 是 function, 用于处理客户端提交的请求。
    2. 工作过程:服务器接收到一个请求时, 根据请求路径找到匹配的函数来处理请求, 返回响应数据。

vue-router 说明

什么是 vue-router

vue 的一个插件库,专门用来实现 SPA 应用

什么是 SPA 应用

  1. 单页 Web 应用(single page web application,SPA)。
  2. 整个应用只有一个完整的页面(一个index.html页面)。
  3. 点击页面中的导航链接不会刷新页面,只会做页面的局部更新。
  4. 数据需要通过 ajax 请求获

配置方式

vue2,只能用vue-router3版本
vue3,只能用vue-router4版本(不写版本默认为vue3专用)

  1. 安装 vue-router 包

npm i vue-router@3 -S

  1. 新建 router 模块
  1. 根据目录新建 router 目录
  2. router 目录 中新建 index.js 文件
  1. 配置 router 模块
  1. 引入 vue-router
  2. 引入自定义组件
  3. 创建路由器
  4. 暴露路由器
  5. 配置路由规则
    • 添加 routes 数组属性
      • 添加 路由配置对象
        1. path:路由路径
          • 必须以 / 开始
        2. compnent:路由对应的组件
        3. name:路由别名
          1. 路由跳转
          2. 路由守卫验证
          3. 详细说明
        4. meta:自定义路由守卫可用的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 引入 vue-router
import VueRouter from 'vue-router'

// 引入自定义组件
import About from "../components/About"
import Home from "../components/Home"

// 创建、暴露 路由器
export default new VueRouter({
routes:[ // 配置路由规则
{
path:"/about", // 配置路由路径
component:About // 配置路由组件
meta:{shuju:"xxx"} // 路由守卫可用的数据
},
{
path:"/home", // 配置路由路径
component:Home // 配置路由组件
meta:{shuju:"xxx"} // 路由守卫可用的数据
}
]
})

  1. 配置 router 模块
  1. 打开 main.js 文件
  2. 引入 vue-router 库
  3. 引入 router 模块
  4. 应用 vue-router 插件
  5. 添加 Vue 实例配置项 router 属性为 router 模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 引入 vue-router 库
import VueRouter from "vue-router"

// 引入 router 模块
import router from "./router"

// 应用插件
Vue.use(VueRouter)

// 创建 vm
new Vue({
el:"#app",
router: router
})

基础实现

不需要引入组件

希望路由展示组件并进行切换,组件中不需要引入其他希望展示的组件,只需要使用 roter-link router-view 就可以实现

路由切换

使用 <router-link></router-link> 标签实现路由的切换

  1. to 属性:配置路由路径
  2. active-class 属性:配置class样式名,切换到的路由应用此配置的样式
1
2
<router-link active-class="ys" to="/about">About</router-link>
<router-link active-class="ys" to="/home">Home</router-link>

路由呈现

使用 <router-view></router-view> 标签实现路由切换时组件显示位置

1
<router-view></router-view>

路由特点

  1. 路由组件通常放在 pages 目录加中,一般组件通常放在 components 目录中
  2. 通过切换,“隐藏”的路由组件,默认是被销毁掉的,“显示”的路由组件,是重新挂载的
  3. 每个组件都有 $route 属性,里面存储着自己的路由信息,每个组件都不同
  4. 每个组件都有 $router 属性,指向同一个对象

增强功能


初始化展示

将路由规则配置项中,path 属性值设置为 “/“,初始打开页面时, router-view 默认显示此路由规则中组件

1
2
3
4
5
6
7
export default new VueRouter({
routes:[
{
path:"/",
component:About
}
})

路由重定向

路由规则配置项中,添加 redirect 属性,值为需要重定向的规则的 path 字符串

1
2
3
4
5
6
7
8
9
10
11
12
export default new vueRouter({
routes:[
{
path:"/",
component:aa,
redirect:"/b" //重定向
},
{
path:"/b",
component:bb
}
})

多级路由

  1. 路由对象中,添加 children 数组属性
  2. children 中添加多个路由对象,作为子级路由
    • 子级路由路径,不可以加 /
  3. 路由切换时,to 属性值需要加上父级路由路径
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
import About from "../pages/About"  //路由组件一般放在 pages 目录中
import Home from "../pages/Home"
import News from "../pages/News"
import Message from "../pages/Message"


export default new VueRouter({
routes:[
{
path:"/about",
component:About
},
{
path:"/home",
component:Home,
children:[ // 添加子级路由
{
path:"news", // 子级路由路由不能加斜杠 /
component:News
},
{
path:"message", // 子级路由路由不能加斜杠 /
component:Message
}
]
}
]
})

跳转方式

  1. 通过 路由路径字符串 进行跳转
    • <router-link> 标签的 to 属性值,配置为 路由路径 字符串
      1
      <router-link to="/about">跳转</router-link>
  2. 通过 路由路径对象 进行跳转
    • <router-link> 标签的 to 属性值
      1. 使用 v-bind 进行绑定
      2. 配置为 路由配置 对象
        1. 定义 path属性路由路径 字符串
    • 1
      2
      3
      4
      5
      6
      7
      <router-link 
      :to="{
      path:'/home/school'
      }"
      >
      跳转
      </router-link>

命名路由

作用

  1. 简化路由跳转 <router-link :to=“{...}”> 标签配置方式
  2. 定义路由守卫时,判断所选组件

用法

  1. 给定义的路由配置项添加 name 属性
  2. 方便 <route-link> to属性 通过 路由路径对象 方式的 name属性 进行跳转
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export default new VueRouter({
routes:[
{
path:"/home",
component:Home,
children:[
{
name:"xiangqing", // 路由配置对象添加name属性
path:"message",
component:Message
}
]
}
]
})
1
2
3
4
5
6
7
<router-link 
:to="{
name: 'xiangqing'
}"
>
跳转
</router-link>

传递参数


query 参数

格式

  1. 参数以 urlencoded 编码格式进行声明
  2. ?name=老刘&age=18

发送

  1. 路由路径字符串
    • <router-link> 标签的 to 属性
      1. 使用 路由路径 字符串
      2. 并添加 urlencoded 编码格式 参数
  • 1
    <router-link to="/home/school?id=66&name=小明">跳转</router-link>
  1. 路由路径对象
    • <router-link> 标签的 to 属性
      1. 使用 v-bind 绑定
      2. 使用 路由路径对象
        1. 使用 name属性path属性 配置跳转
        2. 添加 query 对象,对象中属性 为传递的参数
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <router-link 
    :to="{
    path: '/home/school',
    //name: 'xiangqing'
    query:{ //query 属性
    id : 66,
    name :'小明'
    }
    }"
    >
    跳转
    </router-link>

接收

  1. 通过 组件实例$route属性query属性 获取数据
    1
    2
    3
    mounted(){
    console.log( this.$route.query.xxx )
    }
  2. 通过组件 props 配置项接收数据
    • 路由配置对象 添加 props属性
      1. 属性值:对象
        • 该对象中的所有属性,直接传递给组件的 props
        • 只能传递静态数据
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        export default new VueRouter({
        routes:[ // 配置路由规则
        {
        path:"/home", // 配置路由路径
        component:Home, // 配置路由组件
        children:[
        {
        path:"school",
        component: School,
        props:{id:111,name:"小明"} //对象
        }
        ]
        }
        ]
        })
      1. 属性值:true
        • 只能接收 params参数,即:通过 /xxx/yyy 传递的参数
        • 将接收数据传递给组件的 props
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        export default new VueRouter({
        routes:[ // 配置路由规则
        {
        path:"/home", // 配置路由路径
        component:Home, // 配置路由组件
        children:[
        {
        path:"school",
        component: School,
        props:true // true
        }
        ]
        }
        ]
        })
      1. 属性值:函数
        • 形参:组件的 $route 对象
        • 必须定义对象返回值
        • 可接收 query参数params参数
        • 返回对象的属性传递给组件 props
      • 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
        export default new VueRouter({
        routes:[ // 配置路由规则
        {
        path:"/home", // 配置路由路径
        component:Home, // 配置路由组件
        children:[
        {
        path:"school",
        component: School,
        props:function(route){
        return { // 接收 query 方式传递的数据
        id:route.query.id,
        name:route.query.name
        }
        /*

        return { // 接收 params 方式传递的数据
        id:route.params.id,
        name:route.params.name
        }

        */
        }
        }
        ]
        }
        ]
        })

params 参数

格式

  1. 参数以 路由格式 方式进行传递参数
  2. /老刘/18

配置

  1. 使用 路由路径对象 方式发送,路由配置项中,必须定义 name属性
  2. 路由配置项中 path属性 中,希望接收参数的地方使用 :xxx 占位符进行占位
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export default new VueRouter({
routes:[
{
path:"/home",
component:Home,
children:[
{
name:"xiangqing",
path:"message/:id/:name", //路由路径定义接收参数的占位符
component:Message
}
]
}
]
})

发送

  1. 路由路径字符串
    • <router-link> 标签的 to 属性
      1. 根据配置项中占位位置,给 路由路径 字符串后添加数据
      2. 添加动态数据
        1. v-bind 绑定 to属性
        2. ES6模板字符串,给 路由路径 字符串后添加数据
  • 1
    2
    3
    4
    5
    <!-- 传递静态数据 -->
    <route-link to="/home/school/66/小明">跳转</route-link>

    <!-- 传递动态数据 -->
    <route-link :to="`/home/school/${m.id}/${m.name}`">跳转</route-link>
  1. 路由路径对象
    • <router-link> 标签的 to 属性
      1. 使用 v-bind 绑定
      2. 使用 路由路径对象
        1. 只能使用 name属性 配置跳转
        2. 添加 params 对象,对象中属性 为传递的参数
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <router-link 
    :to="{
    name: 'xiangqing', //只能使用name配置跳转
    params:{ //params 属性
    id : 66,
    name :'小明'
    }
    }"
    >
    跳转
    </router-link>

接收

  1. 通过 组件实例$route属性params属性 获取数据
    1
    2
    3
    mounted(){
    console.log( this.$route.params.xxx )
    }
  2. 通过组件 props 配置项接收数据
    • 路由配置对象 添加 props属性
      1. 属性值:对象
        • 该对象中的所有属性,直接传递给组件的 props
        • 只能传递静态数据
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        export default new VueRouter({
        routes:[ // 配置路由规则
        {
        path:"/home", // 配置路由路径
        component:Home, // 配置路由组件
        children:[
        {
        path:"school",
        component: School,
        props:{id:111,name:"小明"} //对象
        }
        ]
        }
        ]
        })
      1. 属性值:true
        • 只能接收 params参数,即:通过 /xxx/yyy 传递的参数
        • 将接收数据传递给组件的 props
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        export default new VueRouter({
        routes:[ // 配置路由规则
        {
        path:"/home", // 配置路由路径
        component:Home, // 配置路由组件
        children:[
        {
        path:"school",
        component: School,
        props:true // true
        }
        ]
        }
        ]
        })
      1. 属性值:函数
        • 形参:组件的 $route 对象
        • 必须定义对象返回值
        • 可接收 query参数params参数
        • 返回对象的属性传递给组件 props
      • 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
        export default new VueRouter({
        routes:[ // 配置路由规则
        {
        path:"/home", // 配置路由路径
        component:Home, // 配置路由组件
        children:[
        {
        path:"school",
        component: School,
        props:function(route){
        return { // 接收 query 方式传递的数据
        id:route.query.id,
        name:route.query.name
        }
        /*

        return { // 接收 params 方式传递的数据
        id:route.params.id,
        name:route.params.name
        }

        */
        }
        }
        ]
        }
        ]
        })

使用 <router-link></router-link> 标签实现路由的切换

属性介绍:

  1. to
    • 配置路由路径 字符串/对象
    • <router-link :to="...">跳转</router-link>
  2. active-class
    • 配置class样式名,切换到的路由应用此配置的样式
    • <router-link active-class="classname">跳转</router-link>
  3. replace
    • 配置路由跳转时,浏览器历史记录的模式
      1. push 模式
        • 追加历史记录
      2. replace 模式
        • 替换当前历史记录
        • 标签的默认模式
    • <router-link replace>跳转</router-link>

编程触发路由

不借助 <router-link> 实现路由跳转

实现方式

  1. 组件调用 $router 属性,即可调用相关方法进行路由跳转
  2. $router 即为路由器,所有组件共享同一路由器对象

相关方法

  1. push:方法
    • 追加历史记录,进行路由跳转
    • 参数:<router-link> 标签的 路由路径对象 配置方式一致
    • this.$router.push({ 路由路径对象 })
  2. replace:方法
    • 替换当前历史记录,进行路由跳转
    • 参数:<router-link> 标签的 路由路径对象 配置方式一致
    • this.$router.replace({ 路由路径对象 })
  3. back:方法
    • 后退一个历史记录
    • this.$router.back()
  4. forward:方法
    • 前进一个历史记录
    • this.$router.forward()
  5. go:方法
    • 后退、前进 指定个数历史记录(数字正负决定前进、后退)
    • this.$router.go(-3)

缓存路由组件

作用

组件跳转会注销组件,使用 <keep-alive> 包裹显示组件 <router-view> ,就可以让组件保留在内存不被销毁,输入的内容也会暂存在内存

用法

  1. <router-view> 组件外层,包裹组件 <keep-alive>
    • 缓存所有路由跳转的组件
  2. <keep-alive> 组件添加 include 属性
    • 指定需要缓存的组件,其他组件切换时依旧会销毁
    • 属性值:
      • 组件定义时的配置项 name属性
      1. 字符串:
        • 缓存单个组件
        • 单个组件别名字符串
      2. 正则表达式
      3. 数组:
        • 缓存多个组件
        1. v-bind 绑定 include 属性
        2. 数组元素定义组件别名字符串
    • 组件实例name配置项
  3. <keep-alive> 组件添加 exclude 属性
    • 指定的组件不会缓存,其他组件正常缓存
    • 属性值:与 include 一样
1
2
3
4
5
6
7
<keep-alive :include="['school','student']">
<router-view></router-view>
</keep-alive>

<keep-alive include="school">
<router-view></router-view>
</keep-alive>

路由生命周期

路由组件所独有的两个钩子,用于捕获路由组件的激活状态,必须配合 keep-alive 组件使用,router-view 没有被 keep-alive 包裹,没有办法触发activated 和 deactivated 生命周期函数

  1. activated:路由组件被激活时触发 详细解释
    1. 通过路由第一次显示的组件:显示的组件的钩子函数触发顺序 created-> mounted-> activated
    2. 通过路由再次显示其他组件:显示的组件只触发 activated
    3. 不管组件是不是从缓存中显示
  2. deactivated:路由组件失活时触发 详细解释
    1. 通过路由组件被缓存不再显示时,当前组件 deactivated 触发

路由守卫

  • 路由跳转前后
    1. 用于进行的相关处理
    2. 对路由权限进行控制

路由守卫执行顺序

  1. 全局前置路由守卫:最先执行的是 beforeEach 钩子,所有路由开始的时候最先执行
  2. 独享路由守卫:然后就是路由器中,路由规则 router 配置项中的 beforeEnter 方法
  3. 进入守卫:接下来就是 beforeRouteEnter,组件内定义的进入守卫
  4. 离开守卫:最后是 beforeRouteLeave,组件内定义的离开守卫

全局前置路由守卫

作用

  • 路由跳转到目标路由之前
    1. 对跳转进行处理
    2. 对路由权限进行控制

触发条件:

  1. 初始化的时候
  2. 路由跳转到目标路由之前

用法

路由器对象beforeEach 方法实现跳转前控制

  1. 路由器模块中实例化 路由器对象
  2. 路由器对象 调用 beforeEach 方法
  3. beforeEach 方法参数为 回调函数
  4. 回调函数的参数
    1. 参数1:to:
      • 跳转到 的路由组件的相关信息组成的对象
      • 对象
        • name
          • 组件路由别名
        • path
          • 组件路由路径
        • meta
          • 可以自定义的路由配置项验证数据
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            new VueRouter({
            routers:[
            {
            name:"xuexiao",
            path:"/school",
            component:School,
            meta:{ // 自定义路由守卫可以验证的数据
            yz:true,
            sj:"123"
            }
            }
            ]
            })
    2. 参数2:from:
      • 当前 路由组件的相关信息组成的对象
      • 对象
        • name
          • 组件路由别名
        • path
          • 组件路由路径
        • meta
          • 可以自定义的路由配置项验证数据
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            new VueRouter({
            routers:[
            {
            name:"xuexiao",
            path:"/school",
            component:School,
            meta:{ // 自定义路由守卫可以验证的数据
            yz:true,
            sj:"123"
            }
            }
            ]
            })
    3. 参数3:next:
      • beforeEach 回调函数体中执行此函数 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
//实例化路由器
var router = new VueRouter({
routers:[
{
name:"xuexiao",
paht:"/school",
component:School,
meta:{shuju:"xxx"}
},
{
name:"xuesheng",
paht:"/student",
component:Student
},
]
})

//定义路由前置守卫
router.beforeEach(function(to,from,next){
if(to.name == "xuexiao" || to.meta.shuju == "xxx"){ // 验证方式
next()
}
})

//暴露路由器
export default router


全局后置路由守卫

作用

  • 路由跳转到目标路由之后
    1. 进行相关处理
    2. 对路由权限进行控制

触发条件:

  1. 初始化的时候
  2. 路由跳转到目标路由之后

用法

路由器对象afterEach 方法实现跳转前控制

  1. 路由器模块中实例化 路由器对象
  2. 路由器对象 调用 afterEach 方法
  3. afterEach 方法参数为 回调函数
  4. 回调函数的参数
    • 全局后置路由守卫,回调函数,没有第三个参数 next
    1. 参数1:to:
      • 跳转到 的路由组件的相关信息组成的对象
      • 对象
        • name
          • 组件路由别名
        • path
          • 组件路由路径
        • meta
          • 可以自定义的路由配置项验证数据
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            new VueRouter({
            routers:[
            {
            name:"xuexiao",
            path:"/school",
            component:School,
            meta:{ // 自定义路由守卫可以验证的数据
            yz:true,
            sj:"123"
            }
            }
            ]
            })
    2. 参数2:from:
      • 当前 路由组件的相关信息组成的对象
      • 对象
        • name
          • 组件路由别名
        • path
          • 组件路由路径
        • meta
          • 可以自定义的路由配置项验证数据
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            new VueRouter({
            routers:[
            {
            name:"xuexiao",
            path:"/school",
            component:School,
            meta:{ // 自定义路由守卫可以验证的数据
            yz:true,
            sj:"123"
            }
            }
            ]
            })
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
//实例化路由器
var router = new VueRouter({
routers:[
{
name:"xuexiao",
paht:"/school",
component:School,
meta:{shuju:"xxx"}
},
{
name:"xuesheng",
paht:"/student",
component:Student
},
]
})

//定义路由后置守卫
router.afterEach(function(to,from){
if(to.name == "xuexiao" || to.meta.shuju == "xxx"){ // 验证方式
console.log("路由跳转完成了")
}
})

//暴露路由器
export default router


独享路由守卫
  • 对某个路由进行单独配置
    1. 此路由跳转前进行相关处理
    2. 对此路由进行权限控制,是否进行跳转

独享路由守卫可以和全局后置路由守卫一同使用

用法

路由配置项添加 beforeEnter函数 进行配置独享路由守卫

  1. 路由配置象中添加 beforeEnter函数
  2. beforeEnter函数 参数
    1. 参数1:to:
      • 跳转到 的路由组件的相关信息组成的对象
      • 对象
        • name
          • 组件路由别名
        • path
          • 组件路由路径
        • meta
          • 可以自定义的路由配置项验证数据
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            new VueRouter({
            routers:[
            {
            name:"xuexiao",
            path:"/school",
            component:School,
            meta:{ // 自定义路由守卫可以验证的数据
            yz:true,
            sj:"123"
            }
            }
            ]
            })
    2. 参数2:from:
      • 当前 路由组件的相关信息组成的对象
      • 对象
        • name
          • 组件路由别名
        • path
          • 组件路由路径
        • meta
          • 可以自定义的路由配置项验证数据
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            new VueRouter({
            routers:[
            {
            name:"xuexiao",
            path:"/school",
            component:School,
            meta:{ // 自定义路由守卫可以验证的数据
            yz:true,
            sj:"123"
            }
            }
            ]
            })
    3. 参数3: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
28
29
30
31
32
33
34
//实例化路由器
var router = new VueRouter({
routers:[
{
name:"xuexiao",
paht:"/school",
component:School,
meta:{shuju:"xxx"},

beforeEnter(to,from,next){ // 定义独享路由守卫
if(from.name == "xuexiao"){
next()
}
}

},
{
name:"xuesheng",
paht:"/student",
component:Student
},
]
})

//定义路由后置守卫
router.afterEach(function(to,from){
if(to.name == "xuexiao" || to.meta.shuju == "xxx"){ // 验证方式
console.log("路由跳转完成了")
}
})

//暴露路由器
export default router


组件内路由守卫

组件实例配置项中进行配置

  1. 进入守卫
    • beforeRouteEnter函数
    • 通过路由规则,进入该组件时被调用
  2. 离开守卫
    • beforeRouteLeave
    • 通过路由规则,离开该组件时被调用

用法

组件实例配置项 中,定义 beforeRouteEnter (进入)beforeRouteLeave (离开) 函数

参数:

  1. 参数1:to:
  • 跳转到 的路由组件的相关信息组成的对象( beforeRouteEnter函数 表示当前组件)
  • 对象
    • name
      • 组件路由别名
    • path
      • 组件路由路径
    • meta
      • 可以自定义的路由配置项验证数据
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        new VueRouter({
        routers:[
        {
        name:"xuexiao",
        path:"/school",
        component:School,
        meta:{ // 自定义路由守卫可以验证的数据
        yz:true,
        sj:"123"
        }
        }
        ]
        })
  1. 参数2:from:
  • 当前 路由组件的相关信息组成的对象( beforeRouteEnter函数 表示跳转来的组件)
  • 对象
    • name
      • 组件路由别名
    • path
      • 组件路由路径
    • meta
      • 可以自定义的路由配置项验证数据
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        new VueRouter({
        routers:[
        {
        name:"xuexiao",
        path:"/school",
        component:School,
        meta:{ // 自定义路由守卫可以验证的数据
        yz:true,
        sj:"123"
        }
        }
        ]
        })
  1. 参数3:next:
    • 函数体中执行此函数 next(),则正常跳转
    • 函数
1
2
3
4
5
6
export default { // 组件实例中配置
data(){...},
beforeRouteEnter(to, from, next){...} // 进入组件路由守卫
beforeRouteLeave(to, from, next){...} // 离开组件路由守卫
}


路由模式

用于设置页面跳转时,url的展示形式

页面中路由跳转时,并不向服务端重新请求页面,而是通过JS代码实现页面切换,因此 url 路径为 前端路由路径,与服务端无关

名词解释
名词 解释
hash(哈希) url路径 # 及之后的内容统称为 hash(哈希) http://localhost:8080/#/home/message
history 标准的 url 路径
实现方式
  1. 路由器实例化时,添加 mode 配置项
  2. mode 配置项值为 hashhistory 字符串
1
2
3
4
5
6
7
8
9
10
11
12

export default {
mode:"history",
routes:[
{
name:"guanya",
path:"/about",
component:About
}
]
}

模式区别

hash 模式

  1. hash 值,不会包含在HTTP请求中,即:hash 值不会发送给服务器
  2. 如果通过第三方手机APP分享,可能被标记不合法
  3. 兼容性好

history 模式

  1. 地址干净,美观
  2. 兼容性略差
  3. 应用部署上线时需要后端人员支持,解决页面刷新报404问题
    • 在页面路由跳转时,并不向服务端重新请求页面,因此 url 路径只是用于 前端路由,当通过路由跳转后的页面再次刷新时会将当前 ulr 发送给服务端请求页面,因此报404错误(因为路由 url 展示形式是标准的 HTTP 请求路径,因此刷新会发送请求)

webStorage:数据存储

javascript原生存储方式,将数据存储在浏览器

  1. 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
  2. 浏览器通过 Window.sessionStorageWindow.localStorage 属性来实现本地存储机制
  3. 存储的数据只能是字符串
  4. 相关API(两者一样):
    1. 存储
      1. xxxxxStorage.setItem("key","value")
      2. 该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应值
    2. 获取
      1. xxxxxStorage.getItem("key")
      2. 该方法接收一个键名作为参数,返回键名对应的值
      3. 找不到该数据,则返回 null
    3. 删除
      1. xxxxxStorage.removeItem("key")
      2. 该方法接受一个键名作为参数,并把该键名从存储中删除
    4. 清空
      1. xxxxxStorage.clear()
      2. 该方法会清空存储中的所有数据
  5. 存储时长
    1. sessionStorage 存储的内容会随着浏览器窗口关闭而消失
    2. localStorage 存储的内容,需要手动清除才会消失

Vue工具库