vue

vue标签

Posted by アライさん on 2022年08月09日

Vue标签

Vue基础结构

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

<!-- 引入vue -->
<script src="https://unpkg.com/vue@next"></script>
<!-- head中的样式 -->
<style>
#myId {
color: red;
}
.myId {
color:blue;
}
</style>

<!-- body中HTML部分 -->
<div id="Application" style="text-align: center;">
<h1>这里是模板的内容:{{count}}次点击</h1>
<p>count大于10,后面会自动改变:{{type}}</p>
<p>count大于10,后面会自动改变:{{typeFunc()}}</p>
<h1 v-once>这里是模板的内容:<span v-html="countHTML"></span>次点击</h1>
<!-- 用v-bind将id设置为customId的值,将会运用 #myId 这个样式 -->
<h1 v-bind:id="customId">这里是模板的内容:{{count + 10}}次点击</h1>
<h1 :id="customId">这里是模板的内容:{{count + 10}}次点击</h1>
<!-- 用v-bind将class设置为customId的值 -->
<h1 v-bind:[prop]="customId">这里是模板的内容:{{count + 10}}次点击</h1>
<button v-on:click="addCount">按钮</button>
<button @click="addCount">按钮</button>
<div v-for="(item,index) in list">
<p>年龄:{{item.age}}</p>
<p>index: {{index}}</p>
</div>
<div v-for="(value,key,index) in person">
<p>姓名:{{key}}</p>
<p>年龄:{{value}}</p>
<p>index:{{index}}</p>
</div>

<input v-model="searchText" />

</div>

<!-- body中script部分 -->
<script>
const App = {
//类似state的初始化数据
data(){
return {
list:[
{name:"A",age:10},
{name:"B",age:20},
{name:"C",age:15},
],
person:{
name:"A",
age:10,
},
count:0,
countHTML:"<span style='color:red;'>0</span>",
//将customId变量的值设置为myId
customId:"myId"
};
},
//组件生命周期函数,加载时调用
mounted(){

},
//计算属性,页面部分可以直接用{{type}}的方式,绑定type,当count变化时页面也会自动修改
//也可以在methods中用方法实现。用computed会缓存type的值
computed:{
type(){
return this.count>10?"大":"小";
},
//可以为type2手动设置get与set。调用this.type2 = "小"时,count也会被修改
type2(){
get(){
return this.count>10?"大":"小";
},
set(newValue){
if(newValue == "大"){
this.count = 11;
}else{
this.count = 0;
}
}
}
},
//方法
methods:{
addCount(){
this.count=this.count+1;
},
//用这种方法实现,每次都会执行typeFunc()
typeFunc(){
return this.count>10?"大":"小";
}
},
//监听
watch:{
//searchText的值改变时自动触发
searchText(oldValue,newValue){
if(newValue.length > 10){
alert("文本太长");
}
}
}
};
//创建App,绑定到Application这个id的HTML元素上
Vue.createApp(App).mount("#Application");
</script>
```

## Vue标签
* v-once 初始化赋值一次
* v-on:click="" @click="" 点击调用methods方法
* @click.capture 父层先捕获click调用,再轮到子层
* @click.stop 只调用子层(上层)的点击响应(如果不加stop,从上层到下层都会调用)
* v-html 加载包含html标签的内容
* v-bind:style v-bind:id v-bind:class 绑定某项属性,如id、style、class
* v-if v-else-if v-else 条件成立才渲染。v-else-if、v-else必须紧跟v-if之后才起效
* v-show 实际会渲染,只是不展示
* v-for 循环
* v-model 绑定数据实体,比如```<input v-model="searchText" />```
* v-model.lazy 失去焦点后才触发赋值
* v-model.trim 去掉首尾空格后赋值


## 基础属性
* data{return{};} 类似初始化的state
* methods:{} function
* computed:{funcName(){return},} 计算属性,页面可以直接用{{funcName}}绑定
* watch:{variableName(oldValue,newValue){}} 监听,variableName的值改变自动触发
* mounted(){} 组件生命周期函数,加载时调用


## 常用事件类型
* click 点击事件(@click.left="clickFunc"鼠标左键点击)
* dblclick 双击事件
* focus 获取焦点事件(input、select、textarea等)
* blur 失去焦点事件(input、select、textarea等)
* change 内容变更(input、select、textarea等)
* select 选中(input、select、textarea等)
* mousedown 鼠标按键按下(@mousedown.ctrl="mousedown"用这种方法指定按着ctrl并且鼠标按下才触发)
* mouseup 鼠标按键松开
* mousemove 鼠标在组件内移动
* mouseout 鼠标移出组件
* mouseover 鼠标移入组件
* keydown 键盘按下
* keyup 键盘抬起
(@keyup.enter="Func"用这种方法指定enter键松开时触发)
(@keyup.alt.enter="Func"用这种方法指定按住alt再按enter键,松开enter时触发)


## 内置特殊元素
* ```<component>``` 用于渲染动态组件或元素的“元组件”
* ```<slot>``` 模版内的插槽,将内容插入到模板中



## 组件化
需要实现component方法,提供template选项。
```html
<div id="Application">
<my-container>
<template v-slot:header>
<h1>头部</h1>
</template>
<template v-slot:main>
<h1>中间</h1>
</template>
</my-container>
<my-alert @myclick="appfunc" customname="你好"></my-alert>
<my-alert @myclick="appfunc" customname="测试"></my-alert>
<input type="radio" value="pagevalue1" v-model="pageModel"/>页面1
<input type="radio" value="pagevalue2" v-model="pageModel"/>页面2
<!-- component是一种特殊标签,通过is属性来渲染组件 -->
<component v-bind:is="pageModel"></component>
</div>

<script>
const App = Vue.createApp({
data(){
return{
//切换page,component标签渲染的page就不会不同
pageModel:"pageValue1",
};
},
methods:{
appfunc(param){
console.log("点击"+param);
},
},
});
const alertComponent = {
data(){
return {
msg:"警告框提示",
count:0
};
},
methods:{
clickFunc(){
//TODO自己的逻辑

//用$emit可以调用父组件的方法,将this.customname传递给父组件方法
this.$emit('myclick',this.customname);
},

},
//props的简单写法
//props:['customname'],
props:{
//参数customname
customname:{
//String类型的参数
type:String,
//非必传
required:false,
//默认值
default:"",
},
//Number类型的customname2
customname2:Number,
//customname3为string或number类型
customname3:[String,Number],
},
template:`<div><button @click="clickFunc">{{customname}}</button></div>`,
};
const containerComponent = {
template:`<div style="border-style:solid;border-color:red;border-width:10px">
<slot name="header"><label>默认的内容,如果my-container中有内容就不显示</label></slot>
<hr/>
<slot name="main"></slot>
</div>`,
};
const page1 = {
template:`<div style="color:red">页面1</div>`,
};
const page2 = {
template:`<div style="color:blue">页面2</div>`,
};
App.component("pageValue1",page1);
App.component("pageValue2",page2);
App.component("my-alert",alertComponent);
App.component("my-container",containerComponent);
App.mount("#Application");
</script>

在template中使用@click="$emit('myclick'),可以将组件中的@myclick=””点击事件,传递给父组件,调用父组件中的方法。
在template中,要插入html中非自定义的部分,需要用<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
53
54
55
56
57
58
59
60
61
62
63
64
const sub ={
beforeCreate(){
console.log("组件即将创建前");
},
created(){
console.log("组件创建完成");
},
beforeMount(){
console.log("组件即将挂载前");
},
mounted(){
console.log("组件挂载完成");
},
beforeUpdate(){
console.log("组件即将更新前");
},
updated(){
console.log("组件更新完成");
},
activated(){
console.log("被缓存的组件激活时调用");
},
deactivated(){
console.log("被缓存的组件停用时调用");
},
beforeUnmount(){
console.log("组件即将被卸载前调用");
},
unmounted(){
console.log("组件被卸载后调用");
},
errorCaptured(error,instance,info){
console.log("捕获来自子组件的异常时调用");
},
renderTracked(event){
console.log("虚拟DOM重新渲染时调用");
},
renderTrigered(event){
console.log("虚拟DOM被触发渲染时调用");
}
};
```


## 全局错误捕捉和全局数据
```javascript
const App = Vue.createApp({
data(){
return {
};
},
methods:{
}
});
App.config.errorHandler = (err,vm,info) => {
console.log("错误:"+err);
};
App.config.warnHandler = (msg,vm,trace) => {
console.log("警告:"+err);
};
//全局数据
App.config.globalProperties = {
customData:""
};

组件注册

一般使用局部注册,由要使用B组件的A组件自行注册

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
const comp2 = {
template:`<div>组件2</div>`,
};
const comp1 = {
components:{'comp2':comp2},
//comp2由comp1注册
template:`<div>组件1<comp2></comp2></div>`
};
App.component("comp1",comp1);
```



## mixins混入
```javascript
const myMixin = {
props:['title'],
data(){
return {
a:'a',
b:'b',
};
},
};
const com1 = {
//com1也有一个title的props
mixins:[myMixin],
//com1也有a与b。a的值为newA
data(){return{
a:'newA'
};},
};
```


## 自定义指令
自定义一个叫getfocus的vue指令。
有这个指令的组件挂载后将自动获得焦点。
```html
<div id="Application">
<sub-com ></sub-com>
</div>
<script>
const App = Vue.createApp({});
const sub ={
directives:{
getfocus:{
mounted(element,param){
//param.arg为custom,value为true
if(param.value){
element.focus();
}
},
},
},
template:`
<input v-getfocus:custom="true"/>
`,
};
App.component("sub-com",sub);
App.mount("#Application");
</script>
```


## teleport挂载至其他标签
```html
<div id="Application">
<div style="position:absolute;width:50px;">
<my-alert></my-alert>
</div>
</div>
<script>
const App = Vue.createApp({});
App.component("my-alert",{
data(){
return {
show:false,
};
},
template:`
<div>
<button @click="show = true">弹出弹框</button>
</div>
<!-- 将后续代码挂载到body标签下 -->
<teleport to="body">
<div v-if="show" style="text-align:center;padding:20px;position:absolute;top:45%;left:30%;width:40%;border:black solid 2px;background-color:white" >
<h3>弹框</h3>
<button @click="show=false">隐藏弹框</button>
</div>
`,
});
App.mount("#Application");
</script>