vue学习笔记

## 基础 ### 过滤器 通过`{{msg | filter}}`这个形式,可以声明一个带过滤器的模板语法,msg会作为参数传个filter这个函数的第一个参数,将返回值作为最后渲染到DOM的值。 filter是一个JS函数,可以接收多个参数,当参数不唯一时,`{{msg | filter(arg1, arg2)}}`,会将msg作为第一个参数传给filter函数,arg1和arg2作为第二三个参数。 同时,也支持多个过滤器串联,`{{msg | filter1 | filter2}}`会将msg作为参数传给filter1,将处理完成后的返回值作为参数传给filter2。 ### 计算属性 set(一般不写) get(默认写的方法是get方法) 可以理解为缓存,只有在改变时才会重新调用。 ### v-on **修饰符:** `.stop`:阻止事件冒泡 `.prevent`:阻止默认事件。(例:表单submit按钮点击默认会跳转页面) `.{keyCode|keyAlisa}`:键盘指定按键按下时才会触发。(例:@keyup.enter=“enterClick”) `.once`:使得事件只触发一次。 `.native`:监听组件根元素的原生事件。 ### v-for `:key`:为了提高插入删除列表的性能,key不应该重复。(相当于把一个数组变成了链表)​ - vue操作数组时,通过索引修改数组值的方式不是响应式的!不会动态渲染到页面!要使用`splice`来替换值,或者通过vue内建的函数set来更改。例:`Vue.set(this.list, index, "something")` ### v-model **修饰符:** `.lazy`:当键入enter或失去焦点时才更新绑定值,默认是实时输入实时修改的。 `.number`:将输入框中的值转化为数值类型,默认输入的值一律作为字符串。 `.trim`:将输入获取的值前后去空格。 ## 组件化 ### 定义组件 > 定义、注册、使用组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<body>
<div id="app">
<cpn4></cpn4>
<cpn3></cpn3>
<cpn1></cpn1>
</div>
</body>
<script>
// 定义组件
const cpn4 = Vue.extend({
template:`
<div>
<h2>我是标题4</h2>
<p>我是内容4</p>
</div>
`
})
// 注册全局组件
Vue.component("cpn4", cpn4)

// 语法糖写法,直接注册时定义组件
Vue.component("cpn3",{
template:`
<div>
<h2>我是标题3</h2>
<p>我是内容3</p>
</div>
`
})

const cpn2 = Vue.extend({
template:`
<div>
<h2>我是标题2</h2>
<p>我是内容2</p>
</div>
`
})

const cpn1 = Vue.extend({
// 注:模板中只能由一个根元素!推荐用div把模板包裹起来
// 子组件可以使用全局组件和注册的子组件
template: `
<div>
<h2>我是标题1</h2>
<p>我是内容1</p>
<cpn2></cpn2>
<cpn3></cpn3>
</div>
`,
// 注册子组件
components: {
cpn2: cpn2,
}
})

var vm = new Vue({
el: "#app",
data: {},
components: {
// 注册局部组件
cpn1: cpn1
}
})
### 模板分离
1
2
3
4
5
6
7
8
9
10
11
12
13
<template id="tp1">
<div>
<div>模板分离!</div>
<hr>
</div>
</template>

<script>
Vue.component("cpn", {
// 调用template标签属性id="tp1"的内容,实现模板语法分离
template: "#tp1"
})
</script>
### 数据绑定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<body>
<div id="app">
<cpn></cpn>
<cpn1></cpn1>
</div>
</body>

<template id="t1">
<div>
<h2>T1!</h2>
</div>
</template>
<template id="t2">
<div>
<h2>T2!</h2>
<!-- 这里渲染用的是cpn1中data内的值-->
<div>{{ msg }}</div>
</div>
</template>

<script>
Vue.component("cpn1",{
// data要用函数形式,返回值内写数据对象
// 因为组件复用,要保证各自的变量互不干扰
data: function (){
return{
msg: "这是cpn1!"
}
},
template:"#t2"
})

var vm = new Vue({
el: "#app",
data:{},
components: {
cpn:{
template: "#t1",
}
}
})
</script>
### 数据传递 > 父传子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<body>
<div id="app">
<!-- 这里的两个属性名要对应模板的props中-->
<cpn :message="msg" :mv="movie"></cpn>
<!-- <cpn :mv="movie"></cpn> -->
</div>
</body>

<template id="t0">
<div>
<h2>{{ message }}</h2>
<ul>
<li v-for="item in mv">{{ item }}</li>
</ul>
</div>
</template>
<script>
var cpn = {
template: "#t0",
// props传入变量数组
// props: ["message", "mv"]

// props传入对象,可以规定默认值和数据类型
props: {
// message: String
// 传入对象规定默认值和数据类型,传入数组表示可以有多个类型
prop1: [String, Number],
message: {
// type属性规定数据类型
type: String,
// default 规定默认值
default: "aaa",
// required 属性必须传值,不然报错
required: true
},
mv: Array,
testLs: {
type: Array,
// 数组、对象类型default要用函数生产
default: function (){
return []
}
},
prop2: {
// 自定义验证函数
validation: function (value){
return ["yes", "no"].indexOf(value) !== -1
}
}
}

}

var vm = new Vue({
el: "#app",
data:{
msg: "这是数据",
movie: ["哪吒","姜子牙","喜剧之王"]
},
components:{
// 相当于cpn:{...}
cpn
}
})
vm根组件中的data数据,通过cpn标签的v-bind绑定到message和mv属性中,cpn组件通过props将属性值message和mv存储为data,可以被组件内使用,实现数据传递。 - 注:属性值字段不支持驼峰命名,如果使用,在html传值时要转化为短横线命名。例如:`props=["cArc"]`,则在html中传值时要`` > 子传父
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<body>

<div id="app">
<parent></parent>
</div>

</body>

<template id="c">
<div>
<!-- 有参写法-->
<!-- <button @click="onclicked(item)">我是子组件</button>-->
<button @click="onclicked">我是子组件</button>
</div>
</template>
<template id="p">
<div>
<h2>我是父组件</h2>
<!-- 2. 监听事件信号-->
<children @btnclick="clicked"></children>
</div>
</template>

<script>
var children = {
template: "#c",
methods: {
onclicked:function (){
// 1. 发送事件信号
this.$emit("btnclick")
// 有参写法
// this.$emit("btnclick",item)
},
}
}

Vue.component("parent",{
template:"#p",
components: {children},
methods: {
// 3. 回调信号事件函数
clicked: function (){
console.log("子组件被点击了");
alert("1");
}
},
})

var vm = new Vue({
el:"#app",
data:{},
})
</script>
### 组件间访问 > 父访问子 $children \$refs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn ref="aaa"></cpn>
<button @click="btnClick">点我</button>
<button @click="btnRef">Ref点我</button>
</div>
</body>

<template id="c">
<div>
<h2>我是一个组件</h2>
</div>
</template>

<script>
let cpn = {
template:"#c",
data: function (){
return {
msg: "子组件的msg"
}
},
methods:{
printMsg: function (){
console.log("子组件打印的")
}
}
}

const app = new Vue({
el: "#app",
data: {},
methods: {
btnClick:function (){
// 获取所有子组件 --> 列表
console.log(this.$children);
// 访问第一个子组件data中的msg
console.log(this.$children[0].msg);
// 访问第一个子组件的printMsg方法
this.$children[0].printMsg();
},
btnRef: function (){
// 获取所有带有ref属性的子组件 --> {ref属性值:子组件, ...}
console.log(this.$refs);
// 获取ref属性值为aaa的子组件的msg
console.log(this.$refs.aaa.msg);
this.$refs.aaa.printMsg();
}
},
components:{
cpn
}
})
</script>
> 子访问父 $parent \$root(访问根组件)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<body>
<div id="app">
<cpn></cpn>
</div>
</body>

<template id="c">
<div>
<h2>我是一个组件</h2>
<kid></kid>
</div>
</template>

<template id="kid">
<div>
<h2>子子组件</h2>
<button @click="kidClick">子子组件的按钮</button>
</div>
</template>
<script>
let kid = {
template: "#kid",
data: function (){
return {
msg: "子子组件的msg"
}
},
methods: {
kidClick: function (){
console.log("子子组件的parent:");
console.log(this.$parent.msg);
console.log("子子组件的root:");
console.log(this.$root.msg);
}
}
}

let cpn = {
template:"#c",
data: function (){
return {
msg: "子组件的msg"
}
},
methods:{},
components: {
kid
}
}

const app = new Vue({
el: "#app",
data: {
msg: "root的msg"
},
methods: {
btnClick:function (){
// 获取所有子组件 --> 列表
console.log(this.$children);
// 访问第一个子组件data中的msg
console.log(this.$children[0].msg);
// 访问第一个子组件的printMsg方法
this.$children[0].printMsg();
},
btnRef: function (){
// 获取所有带有ref属性的子组件 --> {ref属性值:子组件, ...}
console.log(this.$refs);
// 获取ref属性值为aaa的子组件的msg
console.log(this.$refs.aaa.msg);
this.$refs.aaa.printMsg();
}
},
components:{
cpn
}
})
</script>
### 插槽 > slot 会用标签内部的内容替换插槽,可以预先定义插槽默认值,缺省使用默认值。当存在多个插槽时,标签内的内容会映射到每一个插槽。
1
<slot>这是缺省定义的内容</slot>
> 具名插槽
1
<slot name="xxx"></slot>
这样,在默认使用插槽时,只会替换具名插槽,要使用具名插槽需要添加`slot`属性显式的指定使用的插槽名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<body>
<div id="app">
<!-- 出现两个默认值的标签-->
<cpn></cpn>
<cpn>
<!-- 替换了所有插槽的内容,出现了两个p标签-->
<p>我是插槽内的p标签</p>
</cpn>
<ncpn>
<!-- 替换right插槽-->
<p slot="right">我是右边插槽的</p>
<p slot="left">我是右边插槽的</p>
<!-- 默认替换匿名插槽-->
<p>我是不使用具名插槽的</p>
</ncpn>
</div>

</body>
<template id="cpn">
<div>
<h2>我是组件</h2>
<slot>我是默认值</slot>
<slot>我是默认值</slot>
</div>
</template>

<template id="ncpn">
<div>
<h2>我是具名插槽组件</h2>
<slot>我是默认值</slot>
<slot>我是默认值</slot>
<slot>我是默认值</slot>
<slot name="left"></slot>
<slot name="center"></slot>
<slot name="right"></slot>
</div>
</template>
<script>
let cpn = {
template: "#cpn"
}
let ncpn = {
template: "#ncpn"
}
const app = new Vue({
el: "#app",
components:{
cpn,
ncpn
}
})
</script>
> 作用域插槽 在组件作用域外获取组件的数据。 1. 给slot插槽定义属性,并将属性通过v-bind绑定到需要的data上。 2. 在使用组件时,标签内填充插槽时,通过`v-slot:插槽名=“插槽属性名”`获取到插槽的所有属性,通过`插槽属性.属性名`获取属性名对应的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<body>
<div id="app">
<cpn>
<!-- 默认是访问不到cpn的data属性的-->
<!-- {{ msg }}-->

<!-- 是vue2.6以后的绑定具名插槽方式template标签内掐架属性v-slot:插槽名-->
<!-- v-slot:user="slotProps",是为user插槽的属性去个别名叫slotProps-->
<template v-slot:user="slotProps">
<!-- 获取绑定的data属性,又因为data属性绑定了msg,也就获得了msg属性只-->
{{ slotProps.data }}
</template>
</cpn>
</div>
</body>

<template id="cpn">
<div>
<!-- 在插槽上绑定data属性-->
<slot name="user" :data="msg"></slot>
</div>
</template>

<script>
let cpn = {
template: "#cpn",
data: function (){
return {
msg: "cpn里的data!"
}
}
}
const app = new Vue({
el: "#app",
data: {},
components: {cpn}
})
</script>
## webpack 是一个`打包工具`!

vue学习笔记
http://blog.rainna.xyz/2021/02/17/2021-02-17-vue/
作者
rainnalv
发布于
2021年2月17日
许可协议