文章目录
一、数据相关
1.1、传值 props
props
:props 可以是数组或对象,用于接收来自父组件的数据。- 示例:父组件给子组件传值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!--
在父组件使用子组件时,传递参数:
如果参数是常量,直接写 参数名="参数值",
如果参数是变量,写 :参数名="变量名"
-->
<ball name="乒乓" :num="num1"></ball>
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
//子组件
var ball = {
mounted: function() {
console.log(this.num);
},
props: ["name", "num"], //接收从父组件传过来的参数
template: `<div>我喜欢{{name}},我进了{{num}}个球</div>`
}
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
num1: 10,
},
components: {
ball
}
})
</script>
</body>
</html>
-
运行结果:
-
示例:子组件给父组件传值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<style>
.child {
width: 200px;
height: 200px;
background: lightskyblue;
}
</style>
<body>
<div id="app">
<button @click="changeType">点击按钮显示子组件</button>
<!-- 如果想要在子组件上绑定原生事件,必须使用 .native 的修饰符 -->
<child v-show="type" @childclick="changeTT" @mouseover.native="test"></child>
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
//子组件
var child = {
template: `<div class="child">
我是子组件,我在蓝色的海洋里
<button @click="childFun">点击按钮,隐藏子组件</button>
</div>`,
methods: {
childFun() {
//需要点击按钮改变父组件的type状态值
this.$emit("childclick", false);
}
}
}
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
type: false
},
components: {
child,
},
methods: {
changeType() {
this.type = true;
},
// 接收子组件传过来的参数
changeTT(value) {
this.type = value;
},
test() {
console.log("给子组件绑定的原生事件触发了");
}
}
})
</script>
</body>
</html>
-
运行结果:点击显示子组件
-
运行结果:点击隐藏子组件
1.2、数据 data
data
:Vue 实例的数据对象。- 示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- 使用双大括号显示vue定义的变量内容 -->
<p >{{ msg }}</p>
<p >{{ num }}</p>
<p >{{ list }}</p>
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
msg: 'Hello Vue!',
num: 1,
list: [
{name: "cc",age: 18}
]
},
})
</script>
</body>
</html>
- 运行结果:
1.3、侦听 watch
watch
:侦听器- 虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。
- watch 和 computed 的区别:
1. 计算属性可以一次监听多个值,返回一个结果;watch一次只能监听一个值
2. watch 一般多适用于异步操作或开销比较大的操作
- 语法:
var vm = new Vue({
data: {
a: 1,
b: 2,
c: 3,
d: 4,
e: {
f: {
g: 5
}
}
},
watch: {
// 第一种用法:函数
a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
},
// 第二种用法:绑定方法名
b: 'someMethod',
// 第三种用法:添加deep,该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
},
// 第四种用法:添加immediate,该回调将会在侦听开始之后被立即调用,不需要等值发生改变
d: {
handler: 'someMethod',
immediate: true
},
// 第五种用法:添加回调函数,你可以传入回调数组,它们会被逐一调用
e: [
'handle1',
function handle2 (val, oldVal) { /* ... */ },
{
handler: function handle3 (val, oldVal) { /* ... */ },
/* ... */
}
],
// 第六种用法:通过点语法绑定对象中的属性,从而监听单个属性,而不是整个对象
'e.f': function (val, oldVal) { /* ... */ }
}
})
vm.a = 2 // => new: 2, old: 1
- 示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- 使用双大括号显示vue定义的变量内容 -->
<p>姓:{{firstName}} 名:{{lastName}}</p>
<p>全名:{{fullName}}</p>
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
firstName: "流",
lastName: "星",
fullName: "流星"
},
watch: {
//watch 一次只能监听一个值
firstName: function (newV, oldV) {
console.log("监听到姓变了");
console.log(newV);
console.log(oldV);
return this.fullName = newV + this.lastName;
},
lastName: function (newV, oldV) {
console.log("监听到姓变了");
console.log(newV);
console.log(oldV);
return this.fullName = this.firstName + newV;
}
},
// computed: {
// //计算属性可以一次监听多个值,返回一个结果
// fullName: function() {
// return this.firstName + " " + this.lastName;
// }
// }
})
</script>
</body>
</html>
- 运行结果:
- 深度监听:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- 使用双大括号显示vue定义的变量内容 -->
<input type="text" v-model="userInfo.firstName" />
<input type="text" v-model="userInfo.lastName" />
<p>全名:{{userInfo.fullName}}</p>
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
userInfo: {
firstName: "",
lastName: "",
fullName: ""
}
},
watch: {
userInfo: {
handler(val) {
console.log(val);
return this.userInfo.fullName = val.firstName + " " + val.lastName;
},
deep: true
}
},
})
</script>
</body>
</html>
- 运行结果:
1.4、计算 computed
computed
:计算属性,里面定义的内容是函数,使用当成普通的data数据来使用,返回一个计算后的值。- 特点:
1.避免在模板中写过多逻辑;
2.计算属性的函数可以缓存结果,当结果不发生变化时,计算属性的函数只执行一次
- 语法:
ar vm = new Vue({
data: { a: 1 },
computed: {
// 仅读取
aDouble: function () {
return this.a * 2
},
// 读取和设置
aPlus: {
get: function () {
return this.a + 1
},
set: function (v) {
this.a = v - 1
}
}
}
})
// 相当于调用 get
vm.aPlus // => 2
// 相当于调用 set, 3是参数, -1后 vm.a = 2
vm.aPlus = 3
vm.a // => 2
// 只读取值,vm.a的值不变
vm.aDouble // => 4
vm.a // => 2
- 示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- 使用双大括号显示vue定义的变量内容 -->
原字符串:{{msg}}<br />
<!-- 模板中放入过多的逻辑会使模板不容易维护 -->
字符串翻转:{{msg.split("").reverse().join("")}}<br /><br />
<!-- 直接调用方法,但是结果相同时会多次调用 -->
函数字符串翻转:{{reStr()}}<br />
函数字符串翻转:{{reStr()}}<br /><br />
计算属性:我希望将逻辑写在函数中,并且当结果不发生变化时,进行缓存<br />
<!-- 计算属性可以当成普通的data数据来使用 -->
计算属性字符串翻转:{{reverseMsg}}<br />
计算属性字符串翻转:{{reverseMsg}}<br />
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
msg: "hello world"
},
methods: {
reStr: function() {
console.log("翻转的函数被调用了");
return this.msg.split("").reverse().join("")
}
},
computed: {
reverseMsg: function() {
console.log("计算属性的翻转被调用了");
// 计算属性都会返回一个计算后的值,
return this.msg.split("").reverse().join("")
}
}
})
</script>
</body>
</html>
- 运行结果:
- 计算属性的
getter
、setter
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- 使用双大括号显示vue定义的变量内容 -->
<p>姓:{{firstName}} 名:{{lastName}}</p>
<p>全名:{{fullName}}</p>
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
firstName: "流",
lastName: "星"
},
computed: {
fullName: {
get: function() {
return this.firstName + " " + this.lastName;
},
//如果计算属性的值发生变化,会自动触发 set操作
set: function(newV) {
console.log("计算属性的set触发了", newV);
//使用空格将字符串切割为数组,数组的第一个元素就是姓第二个元素就是名
var nameArr = newV.split(" ");
this.firstName = nameArr[0];
this.lastName = nameArr[1];
}
}
}
})
</script>
</body>
</html>
- 运行结果:
1.5、方法 methods
-
methods
:用来放置定义的方法 -
不应该使用箭头函数来定义 method 函数,因为没有
this
-
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- 使用双大括号显示vue定义的变量内容 -->
<p>{{num}}</p>
<button type="button" @click='plus'>点击+1按钮</button>
<button type="button" @click='plus(2)'>点击+2按钮</button>
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
num: 0,
},
methods: {
plus: function(value) {
// 没有参数时:打印的是MouseEvent对象
// 传了参数后:打印的是传入的参数
console.log(value);
// 通过 typeof 辨别函数是否传参
typeof value === "number" ? this.num += value : this.num++
}
}
})
</script>
</body>
</html>
- 运行结果:先点
+1
再点+2
二、组合相关
2.1、混入 mixins
-
mixins
:接收一个混入对象的数组。-
这些混入对象可以像正常的实例对象一样包含实例选项,这些选项将会被合并到最终的选项中,使用的是和
Vue.extend()
一样的选项合并逻辑。 -
也就是说,如果你的混入包含一个 created 钩子,而创建组件本身也有一个,那么两个函数都会被调用。
-
Mixin 钩子按照传入顺序依次调用,并在调用组件自身的钩子之前被调用。
-
-
语法:
// 在 js 文件 table-options 中定义并导出
export default {
data: {
msg: "hello"
},
computed: {
reMsg() {
return this.msg.split("").reverse().join("");
}
},
created: function () { console.log(1) }
}
// 在.vue文件中导入并使用
import tableOptions from './table-options';
export default {
mixins: [tableOptions],
created: function () { console.log(2) }
}
// 调用顺序为:先打印 1,再打印 2。
- 示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
{{msg}},逆转:{{reMsg}}
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var mymixin = {
data: {
msg: "hello"
},
computed: {
reMsg() {
return this.msg.split("").reverse().join("");
}
}
}
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
},
// 进行 mixin 注册
mixins: [mymixin]
})
</script>
</body>
</html>
- 运行结果:
2.2、继承 extends
extends
:要继承的“基类”组件,使一个组件可以继承另一个组件的组件选项。- 从实现角度来看,extends 几乎和 mixins 相同。
- 通过 extends 指定的组件将会当作第一个 mixin 来处理。
- 然而,extends 和 mixins 表达的是不同的目标。
- mixins 选项基本用于组合功能,而 extends 则一般更关注继承关系。
- 同 mixins 一样,所有选项都将使用相关的策略进行合并。
- 语法:
const CompA = { ... }
const CompB = {
extends: CompA,
...
}
- 示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
{{msg}},逆转:{{reMsg}}
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var child = {
data: {
msg: "hello"
},
computed: {
reMsg() {
return this.msg.split("").reverse().join("");
}
}
}
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
},
extends: child,
})
</script>
</body>
</html>
- 运行结果:
2.3、传值 provider / inject
三、资源相关
3.1、组件 components
- 语法:
components: {name:obj}
- name: 组件名
- obj: 组件的属性
- 示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- 3.使用-->
<firstcom></firstcom>
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
//局部组件
// 1.定义
var firstcom = {
template: `<div>我是局部组件</div>`
}
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
},
//2.注册
components: {
firstcom
}
})
</script>
</body>
</html>
- 运行结果:
3.2、过滤 filters
- 语法:
filters: {
name: function(),
}
- name: 过滤器名称
- function: 执行函数,必须有一个过滤后的返回值
使用方法:变量名 | 过滤器名称
{{name | function()}}
- 示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- 使用双大括号显示vue定义的变量内容 -->
<p>{{BB | toLower}}</p>
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: { // 定义vue对象的数据
aa: 'hello',
BB: 'WORLD',
},
// 局部过滤器
filters: {
toLower: (val) => {
console.log(val);
// 大写字母转小写
return val.toLowerCase();
}
}
})
</script>
</body>
</html>
- 运行结果:
3.3、指令 directive
- 语法:
directive: {
sting:obj,
}
- sting: 指令名
- obj: 指令属性
- 示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- 自定义指令名称前面需要带上 v- 前缀 -->
<p v-basefocus>自定义指令</p>
</div>
<!-- 引入vue插件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 声明vue的对象
var app = new Vue({
el: "#app", // 将vue对象挂载到dom节点
data: {}, // 定义vue对象的数据
directives: { // 所有的局部自定义指令都放在这里
"basefocus": {
//插入时执行的钩子
inserted(el) {
// el:代表的是使用自定义指令的标签
console.log("局部自定义指令运行了");
el.style.border = "2px solid blue";
}
}
}
})
</script>
</body>
</html>
- 运行结果: