Vue快速开始
# Vue常用指令
# 插值表达式
声明式渲染/文本插值
<template>
<div>
<h1>{{ msg }}</h1> //可以是变量
<h2>{{ obj.name }}</h2> //可以是对象.属性
<h3>{{ obj.age > 18 ? '成年' : '未成年' }}</h3> //可以是表达式
</div>
</template>
<script>
export default {
data() { // 格式固定, 定义vue数据之处
return { //固定格式,返回一个数据对象
msg: "hello, vue", // key相当于变量名
obj: {
name: "小vue",
age: 5
}
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# MVVM设计模式
- M:model 数据模型 (data)
- V:view视图(html页面)
- VM:ViewModel视图模型(vue.js)
MVVM 通过 数据双向绑定 让数据自动地双向同步,不需要操作DOM
联系:React是单向数据流,需要通过添加事件处理函数(即受控或非受控组件的事件处理来完成数据和视图一致)。在Vue中不需要这么做,大大减少了对DOM的操作,提高了开发效率
# V-bind
语法:v-bind:属性名="vue变量"
简写形式::
代码示例
<img v-bind:src="url"/>
//简写
<img :src="url"/>
2
3
# V-on
语法:v-on:事件名="methods"
简写形式:@
代码示例
<button v-on:click="count=count+1"/>
<button @click="count=count+1"/>
2
# 事件对象 $event
系统会自动传递事件对象 e
<a @click="one" href="http://www.baidu.com">百度</a>
<a @click="two(10, $event)" href="http://www.taobao.com">淘宝</a>
<script>
export default {
methods: {
// 1. 事件触发, 无传值, 可以直接获取事件对象是
one(e){
e.preventDefault()
},
// 2. 事件触发, 传值, 需要手动传入$event
two(num, e){
e.preventDefault()
}
}
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# v-on事件修饰符
.stop阻止事件冒泡.prevent阻止默认行为.once只执行一次.enter检测回车键.esc检测返回键
代码示例
<input type="text" @keydown.enter="enterFn">
# v-model
v-model 是实现vue变量和表单标签 value 属性,双向绑定的指令
<input type="text" v-model="username">
代码示例
不同表单标签 v-model 绑定的值
<template>
<div>
<div>
<span>来自于: </span>
<!-- 下拉菜单要绑定在select上 -->
<select v-model="from">
<option value="北京市">北京</option>
<option value="南京市">南京</option>
<option value="天津市">天津</option>
</select>
</div>
<div>
<!-- (重要)
遇到复选框, v-model的变量值
非数组 - 关联的是复选框的checked属性(只要选中一个复选框,就会把checked的值true给此变量)
数组 - 关联的是复选框的value属性
-->
<span>爱好: </span>
<input type="checkbox" v-model="hobby" value="抽烟">抽烟
<input type="checkbox" v-model="hobby" value="喝酒">喝酒
<input type="checkbox" v-model="hobby" value="写代码">写代码
</div>
<div>
<span>性别: </span>
<input type="radio" value="男" name="sex" v-model="gender">男
<input type="radio" value="女" name="sex" v-model="gender">女
</div>
<div>
<span>自我介绍</span>
<textarea v-model="intro"></textarea>
</div>
</div>
</template>
<script>
export default {
data(){
return {
from: "",
//hobby:"", //默认是空字符串,但是只要勾选一个复选框,此值即为true
hobby: [],
gender: "男",
intro: ""
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
该指令也有一些功能修饰符
- .number 以parseFloat转成数字类型
- .trim 去除首尾空白字符
- .lazy 在change时触发而非inupt时
# v-text/v-html
v-text把值当成普通字符串显示, v-html把值当做html解析
# v-show/v-if
- v-show 用的display:none隐藏 (频繁切换使用)
- v-if 直接从DOM树上移除
# v-for
<li v-for="(item, index) in arr" :key="index">
{{ item }} ---- {{ index }}
</li>
2
3
这些方法会触发数组改变, v-for会监测到并更新页面(以下即为数组的变更方法)
push()pop()shift()unshift()splice()sort()reverse()
这些方法不会触发v-for更新
slice()filter()concat()
数组变更才会引起界面变化,源地址发生改变才会引起UI发生变化
# vue相关属性方法
# 动态class
将 class 值设置为动态
<div :class{xxx:boolean}>
# 动态 style
将内置 style 设置为动态
<div :style="{css属性:css值}"/>
# vue过滤器
定义
- 全局:
Vue.filter('name',(args)=>{return newValue}) - 局部:
filters:{name:(args)=>{return newValue}}
声明
:src="value | filterName(args)"
# Vue计算属性
一个变量的值, 需要用另外变量计算而得来
computed,定义时是一个函数,但本质上是一个属性(使用时不加小括号)
computed: { //computed: 计算
"计算属性名" () {
return "值" // 必须将最终结果返回
}
}
2
3
4
5
# Vue监听器
可以侦听data/computed属性值改变
watch: {
"被侦听的属性名" (newVal, oldVal){
}
}
2
3
4
5
深度监听 - 立即执行
watch: {
"要侦听的属性名": {
handler (newVal, oldVal) { //这个handler就是之前的简写形式
},
deep: true, // 深度侦听复杂类型内变化
immediate: true, // 立即执行
}
}
2
3
4
5
6
7
8
# Vue组件通信
# 父传子通信
子组件
<template>
<div class="my-product">
<h3>标题: {{ title }}</h3>
<p>价格: {{ price }}元</p>
<p>{{ intro }}</p>
</div>
</template>
<script>
export default {
//PS:props与data,computed都是变量,所以可以在上方通过插值表达式显示
props: ['title', 'price', 'intro']
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
父组件
<Product title="好吃的口水鸡" price="50" intro="开业大酬宾, 全场8折"></Product>
# 子向父通信
子组件
<template>
<div class="my-product">
<h3>标题: {{ title }}</h3>
<p>价格: {{ price }}元</p>
<p>{{ intro }}</p>
<button @click="subFn">宝刀-砍1元</button>
</div>
</template>
<script>
export default {
props: ['index', 'title', 'price', 'intro'],
methods: {
subFn(){
//2.通过$emit触发父组件事件
this.$emit('subprice', this.index, 1) // 子向父
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
父组件
<template>
<Myproduct
@subprice="fn">
</Myproduct>
</template>
<script>
methods: {
fn(inde, price){
//...
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
# 兄弟组件通信
event-bus
使用较不方便,推荐使用vuex
# 组件生命周期
# 阶段函数
| 阶段 | 方法名 | 方法名 |
|---|---|---|
| 初始化 | beforeCreate | created |
| 挂载 | beforeMount | mounted |
| 更新 | beforeUpdate | updated |
| 销毁 | beforeDestroy | destroyed |
# 组件进阶概念
# 动态组件
<p>下面显示注册组件-动态切换:</p>
<div style="border: 1px solid red;">
//PS: 如果comName是UserName,则显示UserName组件,反之则显示UserInfo
<component :is="comName"></component>
</div>
<script>
export default {
data(){
return {
comName: "UserName"
}
},
components: {
UserName,
UserInfo
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 组件缓存/激活非激活生命周期函数
<keep-alive> // keep-alive:保持-活着
<component :is="xxx"></component>
</keep-alive>
<script>
export default {
created(){
console.log("02-UserName-创建");
},
destroyed(){
console.log("02-UserName-销毁");
},
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
被缓存的组件不再创建和销毁, 而是激活和非激活
// 组件缓存下 - 多了2个钩子函数
activated(){
console.log("02-UserName-激活");
},
deactivated(){
console.log("02-UserName-失去激活");
}
2
3
4
5
6
7
# 组件插槽
<slot>
<Pannel>
<div>
插槽填充
</div>
</Pannel>
2
3
4
5
会替换组件中的 <slot> 标签,此标签里可以写默认的结构
# 具名插槽
当一个组件内有2处以上需要外部传入标签的地方
<slot name="title"/>
<Pannel>
<template v-slot:title>
<div>
title
</div>
</template>
</Pannel>
2
3
4
5
6
7
# 作用域插槽
父组件想使用子组件插槽里的数据
父组件
<Pannel>
<template v-slot="scope">
{{scope.row.defaultTwo}}
</template>
</Pannel>
2
3
4
5
子组件
<div class >
<slot :row="defaultObj">{{default.defaultOne}}</slot>
</div>
2
3
在
slot标签上绑定自定义属性和子组件内的值组件使用
v-slot="变量名绑定"变量名绑定后会获取到插槽中的值 ,可直接使用
{{scope.row.defaultTwo}}1
可以让组件更加灵活的适用于不同的场景和项目
# Vue自定义指令
- 全局注册
Vue.directive("指令名",{
"inserted"(el){
}
})
2
3
4
5
- 局部注册
directives:{
"指令名":{
inserted(el){
}
}
}
2
3
4
5
6
7
# 自定义指令传值
// 目标: 自定义指令传值
Vue.directive('color', {
inserted(el, binding) { //binding里边存储了指令的很多信息,binding.value存储的是指令传递过来的数据,比如下边的colorStr变量
el.style.color = binding.value
},
// 注意:
// inserted方法 - 指令所在标签, 被插入到网页上触发(一次)
// update方法 - 指令对应数据/标签更新时, 此方法执行
update(el, binding) { //数据更新时,执行此方法(如果不写这个方法,那么colorStr变量改变值,颜色不会发生改变)
el.style.color = binding.value
}
})
2
3
4
5
6
7
8
9
10
11
12
<p v-color="colorStr" @click="changeColor">修改文字颜色</p>
<script>
data() {
return {
colorStr: "red",
};
},
methods: {
changeColor() {
this.colorStr = 'blue';
},
},
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
# $nextTick/$refs
$refs
<h1 ref = "myH1">
</h1>
<script>
mounted(){
console.log(this.$refs.myH1)
}
</script>
2
3
4
5
6
7
8
9
可以访问该 DOM 所有的属性和方法
$nextTick
点击搜索按钮自身隐藏,出现输入框并马上处于激活状态
<template>
<div>
<input ref="myInp" type="text" placeholder="这是一个输入框" v-if="isShow">
<button v-else @click="btn">点击我进行搜索</button>
</div>
</template>
<script>
// 目标: 点按钮(消失) - 输入框出现并聚焦
// 1. 获取到输入框
// 2. 输入框调用事件方法focus()达到聚焦行为
export default {
data(){
return {
isShow: false
}
},
methods: {
//注意函数内使用await,需要添加async
async btn(){
this.isShow = true;
// this.$refs.myInp.focus() //PS:会报错,myInp是undefined
// 原因: data变化更新DOM是异步的
// 输入框还没有挂载到真实DOM上
// 解决:
// this.$nextTick(() => {
// this.$refs.myInp.focus()
// })
// 扩展: await取代回调函数
// $nextTick()原地返回Promise对象
await this.$nextTick() //等待执行完毕之后,再获取焦点
this.$refs.myInp.focus()
}
}
}
</script>
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