1
- #### 一键生成.vue文件模板
1
+ ### 一键生成.vue文件模板
2
2
3
3
我们借用vscode自带的功能
4
4
48
48
49
49
50
50
51
- #### 重置data或者获取data初始值
51
+ ### 重置data或者获取data初始值
52
+
53
+ 在某些情况我们可能要重置data上面的某些属性
52
54
53
55
``` javascript
54
56
this .$data // 获取当前状态的data
@@ -58,7 +60,7 @@ Object.assign(this.$data,this.$options.data()) //重置data
58
60
59
61
60
62
61
- #### 强制刷新组件
63
+ ### 强制刷新组件
62
64
63
65
``` javascript
64
66
this .$forceUpdate () // 迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
@@ -80,7 +82,21 @@ key++;
80
82
81
83
82
84
83
- #### 长列表优化
85
+ ### performance[ 文档] ( https://cn.vuejs.org/v2/api/#performance )
86
+
87
+ 进行组件初始化、编译、渲染和打补丁的性能追踪
88
+
89
+ ``` javascript
90
+ // main.js
91
+ const isDev = process .env .NODE_ENV !== " production" ;
92
+ Vue .config .performance = isDev;
93
+ ```
94
+
95
+ ![ img] ( ../images/vue/1575336533.jpg )
96
+
97
+
98
+
99
+ ### 长列表优化
84
100
85
101
当我们遇到很多的数据展示且不需要响应式变化时,我们就可以使用[ Object.freeze] ( https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze ) 进行优化;
86
102
@@ -89,25 +105,113 @@ key++;
89
105
当我们把一个对象传给实例的data,Vue会使用` Object.defineProperty ` 把这些属性响应式,使用了 [ Object.freeze] ( https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze ) 之后,不仅可以减少 ` observer ` 的开销,还能减少不少内存开销,Vue有人提了相关[ issue] ( https://github.com/vuejs/vue/issues/4384 )
90
106
91
107
``` javascript
92
- this .list = Object .freeze (Object .assign ({}, this .list ))
108
+ export default {
109
+ data (){
110
+ return {
111
+ list: []
112
+ }
113
+ },
114
+ async created () {
115
+ const list = await this .$axios .get (" /goodsList" );
116
+ this .list = Object .freeze (list);
117
+ }
118
+ };
119
+
93
120
```
94
121
95
122
96
123
97
- #### $attrs和$listeners的使用场景
124
+ ### $attrs & $listeners
125
+
126
+ 我们平时组件传值props跟emit用的比较多,但是有些时候他们不是父子组件就比较麻烦了
127
+
128
+ 现在三个嵌套的组件, A -> B -> C ,我们现在要从A传值给C, 或者C通过emit传值给A
129
+
130
+ ![ img] ( C:\Users\Administrator\Desktop\txw\note\images\vue\1575352877.jpg )
131
+
132
+ A组件
133
+
134
+ ``` vue
135
+ <template>
136
+ <div>
137
+ <B :name="name" @changeName="changeName"/>
138
+ </div>
139
+ </template>
140
+
141
+ <script>
142
+ import B from './B'
143
+ export default {
144
+ components: {
145
+ B
146
+ },
147
+ data () {
148
+ return {
149
+ name:'蜡笔小新'
150
+ }
151
+ },
152
+ methods: {
153
+ changeName(msg){
154
+ this.name = msg
155
+ }
156
+ }
157
+ }
158
+ </script>
159
+
160
+ ```
161
+
162
+ B组件
163
+
164
+ ``` vue
165
+ <template>
166
+ <div>
167
+ <C v-bind="$attrs" v-on="$listeners"/>
168
+ </div>
169
+ </template>
170
+ <script>
171
+ import C from './C'
172
+ export default {
173
+ components: {
174
+ C
175
+ },
176
+ }
177
+ </script>
178
+
179
+ ```
180
+
181
+ C组件
182
+
183
+ ``` vue
184
+ <template>
185
+ <div>
186
+ {{name}}
187
+ <button @click="changeName">修改</button>
188
+ </div>
189
+ </template>
190
+ <script>
191
+ export default {
192
+ props:{
193
+ // A组件传来的
194
+ name:{
195
+ type:String
196
+ }
197
+ },
198
+ methods: {
199
+ changeName(){
200
+ this.$emit('changeName','coder') //传给A组件
201
+ }
202
+ }
203
+ }
204
+ </script>
98
205
99
- ``` javascript
100
- A - > B - > C
101
- $attrs // 跨组件传值 A传值给C 在B组件上写上 v-bind="$attrs"
102
- $listeners // 跨组件执行事件 在C执行emit传值给A组件 在B组件上写上 v-on="$listeners"
103
- 一般在对UI 组件进行二次封装时,只写上常用的一些属性跟方法,然后写上$attrs和$listners,我们使用组件时就可以直接使用原组件的属性跟方法
104
206
```
105
207
208
+ 这样我们就实现了跨组件传值,一般在对UI组件进行二次封装时,只写上常用的一些属性跟方法,然后写上$attrs和$listners,我们使用组件时就可以直接使用原组件的属性跟方法
209
+
106
210
107
211
108
- #### .sync修饰符
212
+ ### .sync修饰符
109
213
110
- 因为vue带来的双向绑定给开发带来了便利,同时也带来了代码维护上的问题,我们可以在子组件直接修改父组件穿的prop,新版本直接修改会报warn,推荐以 ` update:myPropName ` 的模式触发事件取而代之
214
+ 因为vue带来的双向绑定给开发带来了便利,同时也带来了代码维护上的问题,我们可以在子组件直接修改父组件穿的prop,新版本直接修改会报warn,官方推荐以 ` update:myPropName ` 的模式触发事件取而代之
111
215
112
216
``` vue
113
217
<text-document v-bind:title.sync="msg"></text-document>
@@ -118,7 +222,84 @@ $listeners //跨组件执行事件 在C执行emit传值给A组件 在B组件上
118
222
this.$emit('update:title', newTitle)
119
223
```
120
224
121
- #### 自定义组件的 ` v-model ` [ 文档] ( https://cn.vuejs.org/v2/guide/components-custom-events.html#自定义组件的-v-model )
225
+
226
+
227
+ ### hook
228
+
229
+ 这是一个文档中没有的api,在源码中存在的,我们可以看vue源码_init函数中是通过callHook调用生命周期的
230
+
231
+ ``` javascript
232
+ vm ._self = vm;
233
+ initLifecycle (vm);
234
+ initEvents (vm);
235
+ initRender (vm);
236
+ callHook (vm, ' beforeCreate' );
237
+ initInjections (vm); // resolve injections before data/props
238
+ initState (vm);
239
+ initProvide (vm); // resolve provide after data/props
240
+ callHook (vm, ' created' );
241
+ ```
242
+
243
+ 然后我们找到callHook,我们可以看到vm._ hasHookEvent为true时就会执行 vm.$emit('hook:' + hook)
244
+
245
+ ``` javascript
246
+ function callHook (vm , hook ) {
247
+ // #7573 disable dep collection when invoking lifecycle hooks
248
+ pushTarget ();
249
+ var handlers = vm .$options [hook];
250
+ var info = hook + " hook" ;
251
+ if (handlers) {
252
+ for (var i = 0 , j = handlers .length ; i < j; i++ ) {
253
+ invokeWithErrorHandling (handlers[i], vm, null , vm, info);
254
+ }
255
+ }
256
+ if (vm ._hasHookEvent ) {
257
+ vm .$emit (' hook:' + hook);
258
+ }
259
+ popTarget ();
260
+ }
261
+ ```
262
+
263
+ 然后我们通过` _hasHookEven ` t找到相关代码,当通过$on去监听时,如果事件名以 hooks: 作为前缀,vm._ hasHookEvent就会被置为true
264
+
265
+ ``` javascript
266
+ var hookRE = / ^ hook:/ ;
267
+ Vue .prototype .$on = function (event , fn ) {
268
+ var vm = this ;
269
+ if (Array .isArray (event )) {
270
+ for (var i = 0 , l = event .length ; i < l; i++ ) {
271
+ vm .$on (event [i], fn);
272
+ }
273
+ } else {
274
+ (vm ._events [event ] || (vm ._events [event ] = [])).push (fn);
275
+ // optimize hook:event cost by using a boolean flag marked at registration
276
+ // instead of a hash lookup
277
+ if (hookRE .test (event )) {
278
+ vm ._hasHookEvent = true ;
279
+ }
280
+ }
281
+ return vm
282
+ };
283
+ ```
284
+
285
+ 使用场景
286
+
287
+ ``` javascript
288
+ mounted (){
289
+ let i = 0
290
+ this .timer = setInterval (()=> {
291
+ console .log (++ i);
292
+ },1000 )
293
+
294
+ this .$on (' hook:beforeDestroy' ,()=> {
295
+ clearInterval (this .timer )
296
+ })
297
+ }
298
+ ```
299
+
300
+
301
+
302
+ ### 自定义组件的 ` v-model ` [ 文档] ( https://cn.vuejs.org/v2/guide/components-custom-events.html#自定义组件的-v-model )
122
303
123
304
一个组件上的 ` v-model ` 默认会利用名为 ` value ` 的 prop 和名为 ` input ` 的事件,但是像单选框、复选框等类型的输入控件可能会将 ` value ` 特性用于[ 不同的目的] ( https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#Value ) 。` model ` 选项可以用来避免这样的冲突:
124
305
@@ -145,9 +326,11 @@ Vue.component('base-checkbox', {
145
326
<base-checkbox v-model="lovingVue"></base-checkbox>
146
327
```
147
328
148
- 这里的 ` lovingVue ` 的值将会传入这个名为 ` checked ` 的 prop。同时当 ` 触发一个 ` change` 事件并附带一个新的值的时候,这个 ` lovingVue` 的属性将会被更新。
329
+ 这里的 ` lovingVue ` 的值将会传入这个名为 ` checked ` 的 prop。同时当 触发一个` change ` 事件并附带一个新的值的时候,这个 ` lovingVue ` 的属性将会被更新。
330
+
331
+
149
332
150
- #### 自动引入route文件
333
+ ### 自动引入route文件
151
334
152
335
当我们项目比较大的时候,我们就会把路由文件根据不同的业务模块拆分
153
336
@@ -191,7 +374,7 @@ export default new Router({
191
374
192
375
193
376
194
- #### 更新缓存的组件
377
+ ### 更新缓存的组件
195
378
196
379
使用vue的生命周期函数[ activated] ( https://cn.vuejs.org/v2/api/#activated )
197
380
@@ -202,11 +385,9 @@ export default new Router({
202
385
203
386
204
387
388
+ ### watch的高级用法
205
389
206
-
207
- #### watch的高级用法
208
-
209
- 1.当我们watch一个值时,第一次不会指向,只有值发生变化时才会执行,此时需要我们将immediate设为true
390
+ 1.当我们watch一个值时,第一次不会执行,只有值发生变化时才会执行,此时需要我们将immediate设为true
210
391
211
392
2.普通的watch方法无法无法监听对象内部属性的改变,我们把deep设为true时就能进行深度监听了
212
393
@@ -229,7 +410,7 @@ new Vue({
229
410
230
411
231
412
232
- #### 异步数据传值给子组件
413
+ ### 异步数据传值给子组件
233
414
234
415
这是新手都会遇到的问题,父组件异步获取数据传给子组件,子组件拿不到值,下面是我平时的解决方案
235
416
245
426
246
427
247
428
248
- #### 巧用slot
429
+ ### 巧用slot
249
430
250
- 插槽是一个很好用的api
431
+ 插槽是一个很好用的api,特别是在封装组件的时候,让组件有更多扩展的空间
432
+
433
+ ``` html
434
+ //封装通用header组件
435
+ <template >
436
+ <div class =" cc-header header" >
437
+ <cc-svg-icon
438
+ @click =" goback"
439
+ icon-class =" left-arrow"
440
+ class-name =" left-arrow"
441
+ size =" .2rem"
442
+ ></cc-svg-icon >
443
+ <div v-if =" $slots.center" class =" cc-header-center" >
444
+ <slot name =" center" ></slot >
445
+ </div >
446
+ <p class =" cc-header-title" v-else >{{title}}</p >
447
+ <div class =" cc-header-right" >
448
+ <slot name =" right" ></slot >
449
+ </div >
450
+ </div >
451
+ </template >
452
+ ```
453
+
454
+ ``` html
455
+ //使用组件
456
+ <cc-header >
457
+ <template slot =" center" >
458
+ <van-search class =" search-input" placeholder =" 通用名" v-model =" params.search" />
459
+ </template >
460
+ <template slot =" right" >
461
+ <div class =" search-btn" @click =" toSearch" >搜索</div >
462
+ </template >
463
+ </cc-header >
464
+ ```
251
465
252
466
253
467
254
- #### 开发插件
468
+ ### 开发插件
255
469
256
470
Vue.js 的插件应该暴露一个 ` install ` 方法。这个方法的第一个参数是 ` Vue ` 构造器,第二个参数是一个可选的选项对象:
257
471
@@ -292,7 +506,7 @@ Vue.use(MyPlugin)
292
506
293
507
294
508
295
- #### ref
509
+ ### ref
296
510
297
511
` ref ` 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 ` $refs ` 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
298
512
@@ -305,15 +519,22 @@ Vue.use(MyPlugin)
305
519
306
520
307
521
308
- #### hook
522
+ ### 一些不常用却很牛逼的api
309
523
310
- 这是一个文档中没有的api
524
+ ##### [ Vue.observable( object ) ] ( https://cn.vuejs.org/v2/api/#Vue-observable )
311
525
312
- #### 一些不常用却很牛逼的api
526
+ 让一个对象可响应。Vue 内部会用它来处理 ` data ` 函数返回的对象。当我们项目没使用vuex时,就可以使用这个api
313
527
314
- ##### [ Vue.observable( object )] ( https://cn.vuejs.org/v2/api/#Vue-observable )
528
+ ``` javascript
529
+ import Vue from ' vue'
530
+ export const store = Vue .observable ({ count: 0 })
531
+ export const mutations = {
532
+ setCount (count ) {
533
+ store .count = count
534
+ }
535
+ }
315
536
316
- 让一个对象可响应。Vue 内部会用它来处理 ` data ` 函数返回的对象。
537
+ ```
317
538
318
539
##### [ v-pre] ( https://cn.vuejs.org/v2/api/#v-pre )
319
540
@@ -352,4 +573,4 @@ Vue.use(MyPlugin)
352
573
353
574
#### 总结
354
575
355
- 学习技术就是多水群多刷掘金 ,你就会知道自己多菜!!!!!然后偷偷去学习大神的技术
576
+ 学习技术就要多刷掘金 ,你就会知道自己多菜!!!!!然后偷偷去学习大神的技术
0 commit comments