0


猿创征文 |《深入浅出Vue.js》打卡Day7

目录

第15章 指令的奥秘

指令

Vue.js

提供的带有

v-

前缀的特殊特性,用于辅助开发者渲染页面的基本结构。

15.1 指令原理概述

指令相关的知识贯穿

Vue.js

内部各个核心技术点。在模板解析阶段,我们在将指令解析到

AST

directives

属性中,然后使用

AST

生成代码字符串的过程中实现某些内置指令的功能,最后在虚拟DOM渲染的过程中触发自定义指令的钩子函数使指令生效。
在这里插入图片描述

15.2 指令的分类

15.2.1 内容渲染指令

  • v-text 几乎不用
<p v-text="age">年龄</p>// 会覆盖元素内部原有的内容
  • {{}} 插值表达式(Mustache) 实际开发中用的最多 支持JS语句
<!-- {{}} 只是内容的占位符,不会覆盖原有的内容 --><p>年龄:{{age}}</p>
  • v-html 可以把包含HTML标签的字符串渲染到页面
<p v-html="info"></p>
 
 info: "<h2 color='red'>个人信息</h2>",

15.2.2 属性绑定指令

  • v-bind 给元素属性动态绑定值,简写英文 :
 姓名: <input type="text" v-bind:placeholder="tips">
 
  tips: '请输入名称',

补充 :在使用

v-bind

属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号,支持JS运算,例如:

<div :title=" 'box' + index ">这是一个div</div>

15.2.3 事件绑定指令

  • v-on 事件绑定,简写为@
<button v-on:click="add(2)">+1</button>
 
 methods: {
                // add:function(){} 简写如下
                add(n){
                    this.count += n; // this就是vm实例,它里面有个count值
                },
                reduce(){
                    this.count -=1;}}

15.2.4 双向绑定指令

  • v-model 事件修饰符
<--.number 自动将用户的输入的内容进行处理,转换为数字格式
          .trim 自动过滤用户输入的首尾空白字符
          .lazy 在失去焦点的时候更新--><input type="text" v-model.number="n1">+<input type="text" v-model.number="n2">={{n1+n2}}<hr><input type="text" v-model.trim="username"><button @click="showbtn">点击获取名字</button><hr><input type="text" v-model.lazy="username">

15.2.5 条件渲染指令

  • v-if / v-show 按需控制DOM的显示与隐藏
<!-- v-if 是动态创建和动态移除来实现的   一般这个用的多--><!-- 如果刚进入页面的时候,某些元素不需要被展示,而且后期这个元素很可能不需要被展示,v-if性能会更好 --><p v-if="flag">这是被v-if所控制的元素</p><!-- v-show 是动态添加或移除style="display:none"样式来实现元素显示与隐藏 --><!-- 如果要频繁的切换元素的显示状态,用v-show性能最好的 --><p v-show="flag">这是被v-show所控制的元素</p>
  • v-if v-else-if v-else
<div v-if="type=='A'">优秀</div><div v-else-if="type=='B'">良好</div><div v-else-if="type=='C'">一般</div><div v-else="type=='D'">较差</div>

15.2.6 列表渲染指令

  • v-for 基于一个数组来循环渲染一个列表结构
<tbody>
// index 是索引 
// list是data中的列表
// v-for 指令,一定要绑定一个:key属性,尽量把id作为key的值 
// key值不能重复,否则会在终端报错
// 官方对key的值类型,是有要求的:字符串或者数字类型
    <tr v-for="(item ,index)in list" :key="item.id" :title="item.name"><td>{{index}}</td><td>{{item.id}}</td><td>{{ item.name })</td></tr></tbody>

第16章 过滤器的奥秘

Vue.js 

运行我们自定义过滤器来格式化文本。它可以用在两个地方:双花括号插值 和 **

v-bind

表达式**。它应该被添加在JavaScript表达式的尾部,由“管道”符号指示:

// 在双花括号中
{{message | capitalize}}

// 在v-bind中
<div v-bind:id="rawId | formatId"></div>

此外,过滤器可以串联,比如:

{{message | filterA | filterB}}

在这个例子中,fillterA被定义为接收单个参数的过滤器函数,表达式message的值多为参数传入到fillterA过滤器函数中。然后将过滤函数fillterA的执行结果当作参数传递给fillterB函数。

过滤器还可以接收参数,比如:

{{message | filterA('arg1','arg2')}}

在这个例子中,filterA被定义为接收三个参数的过滤器函数。其中message的值作为第一个参数,普通字符串‘arg1’作为第二个参数,表达式’arg2’的值作为第三个参数

16.1 过滤器原理概述

{{message | capitalize}}
这个过滤器在模板编译阶段会编译成下面的样子:
_s(_f("capitalize")(message))

这个代码原理简单的来说,其实就是执行了

capitalize

过滤器函数并把message当作参数传递过去,接着将

capitalize

过滤器处理后的结果当作参数传递给

toString

函数。最终

toString

函数执行后的结果会保存到

VNode

中的text属性,去渲染视图。

其中

_s

函数是

toString

函数的别名,

_f

函数是

resolveFilter

的别名,其作用是从

this.$options.filters

中找出注册的过滤器并返回。

resolveFilter的内部原理

_f

函数是

resolveFilter

函数的别名。

resolveFilter

代码如下:
在这里插入图片描述

resolveAsset 

查找过滤器代码如下:
在这里插入图片描述
在这里插入图片描述
这里首先判断参数id 的类型(它是过滤器id ),它必须是字符串类型,如果不是,则使用return语句终止函数继续执行。随后声明变量

assets

并将

options[type]

保存到该变量中。事实上,

resolveAsset

函数除了可以查找过滤器外,还可以查找组件和指令。

本例中变量

assets

中保存的是过滤器集合。
1、通过

hasOwn

函数检查

assets

自身是否存在

id

属性,如果存在,则直接返回结果。

hasOwn

函数基于

0bject.prototype.hasOwnProperty

实现。
2、如果不存在,则使用函数

 camelize

id驼峰化

之后再检查

assets

身上是否存在将

id驼峰化

之后的属性。
3、如果驼峰化后的属性也不存在,那么使用

capitalize

函数将

id的首字母大写

后再次检查

assets

中是否存在。
4、如果还是找不到,那么按照前面的顺序重新查找―遍属性,不同的是这次将检查

原型链

.'查找原型链很简单:只需要访问属性即可。如果找到,则返回过滤器。如果找不到,那么在非生产环境下在控制台打印警告。最后,无论是否找到,都返回查找结果。

注册过滤器有两种途径:注册全局过滤器在组件的选项中定义本地的过滤器。全局注册的过滤器会保存在

Vue

构造函数中。

resolveAsse

函数在查找过滤器的过程中并没有去

vue

构造函数中搜索过滤器。这是因为在初始化

Vue.js

实例时,把全局过滤器与组件内注册的过滤器合并到

this.$options.filters

中了,而

this.$options.filters

其实同时保存了全局过滤器和组件内注册的过滤器。

resolveAsset

只需要从

this.$options.filters

中查找过滤器即可。

16.2 解析过滤器

parseFilters

函数,专门用来解析过滤器,它可以将模板过滤器解析成过滤器函数调用表达式。逻辑就是,解析出过滤器的列表后,循环过滤器列表并拼接一个字符串即可。

第17章 最佳实践

17.1 为列表渲染设置属性key

key

这个特殊属性主要用在

Vue.js

的虚拟DOM算法中,在更新子节点时,需要从旧虚拟节点列表中查找与新虚拟节点相同的节点进行更新。如果这个查找过程设置了属性key,那么查找速度会快很多。所以无论何时,建议尽可能地在使用v-for时提供key。

17.2 在 v-if / v-if-else / v-else 中使用key

如果一组

v-if + v-else

的元素类型相同,最好使用属性key。默认情况下,

Vue.js

会尽可能高效地更新DOM。这意味着,当它在相同类型的元素之间切换时,会修补已存在的元素,而不是将旧的元素移除,然后再同一位置添加一个新元素。如果本不相同的元素被识别为相同,则会出现意料之外的副作用。如果添加了属性

key

,那么在对比虚拟DOM时,则会认为它们是两个不同的节点,于是会将旧元素移除并在相同的位置添加一个新元素,从而避免意料之外的副作用。

17.3 路由切换组件不变

在使用

Vue.js

开发项目时,最常遇到的一个典型问题就是,当页面切换到同一个路由但不同参数的地址时,组件的生命周期钩子并不会重新触发。
这是意味

vue-router

会识别出两个路由使用的是同一个组件从而进行复用,并不会重新创建组件,因此组件的生命周期钩子自然也不会被触发。

下面总结3个方法来解决这个问题:
1、路由导航守卫

beforeRouteUpdate

组件的生命周期钩子虽然不会重新触发,但是路由提供的

beforeRouteUpdate

守卫可以被触发。因此,只需要把每次切换路由时需要执行的逻辑放到

beforeRouteUpdate

守卫中即可。这是比较推荐的一种方式。

2、观察

$route

对象的变化
通过

watch

可以监听到路由对象发生的变化,从而对路由变化作出响应。
在这里插入图片描述
这个方式也可以解决上述问题。但代价是组件内多了一个

watch

,这会带来依赖追踪的内存开销。如果最终选择使用

watch

解决这个问题,推荐只观察自己需要的

query

,这样有利于减少不必要的请求。

3、为

router-view

组件添加属性

key

这中做法非常取巧,非常“暴力”,但非常有效。它本质上是利用虚拟DOM在渲染时通过

key

来对比两个节点是否相同的原理。通过给

router-view

组件设置

key

,可以使每次切换路由时的

key

都不一样,让虚拟DOM认为

router-view

组件时一个新节点,从而先销毁组件,让后再重新创建新组件。即使是相同的组件,但是如果url变了,key就变了,

Vue.js

就会重新创建这个组件。所以组件内的生命周期会重复触发。

优点:简单粗暴,改动小;
缺点:每次切换路由组件时都会被销毁并且重新创建,非常浪费性能。

17.4 区分Vuex与props的使用边界

通常,在项目开发中,业务组件会使用

Vuex

维护状态,使用不同组件统一操作

Vuex

中的状态。这样不论是父子组件间的通信还是兄弟组件间的通信,都很容易。

对于通用组件,我会使用

props

语句事件进行父子组件间的通信(通用组件不需要兄弟组件间的通信)。这样做是因为通用组件会拿到各个业务组件中使用,它要与业务解耦,所以需要使用

props

获取状态。

17.5 避免 v-if 和 v-for 一起使用

Vue.js

处理指令时,

v-for

v-if

具有更高的优先级。

17.6 为组件样式设置作用域

Css 的规则都是全局的,任何一个组件的样式规则都对整个页面有效。因此,我们很容易在一个组件中写了某个样式,而不小心影响了另一个组件的样式,或者自己的组件被第三方库的CSS影响了。

解决方法:在Vue.js中,可以通过

scoped

特性或

CSS Modules

(一个基于class的类似BEM的策略)来设置组件式作用域。
在这里插入图片描述
在这里插入图片描述
在组件库,我们应该更倾向于选用基于class的策略而不是scoped特性

17.7 避免在scoped中使用元素选择器

scoped

样式中,类选择器比元素选择器更好,因此大量使用元素选择器是很慢的。

17.8 避免隐性的父子组件通信

我们应该优先通过

prop

和事件进行父子组件之间的通信,而不是使用

this.$parent

或改变

prop

17.9 单文件组件的文件名的大小写

单文件组件的文件名应该始终是单词首字母大写,或者始终是横线连接的;

应用特定样式和约定的基础组件(也就是展示类的,无逻辑的或无状态的组件)应该全部以一个特定的前缀开头,比如

Base

App

V


在这里插入图片描述
在这里插入图片描述
只拥有单个活跃实例的组件以

The

前缀命名,以示其唯一性;
在这里插入图片描述
和父组件紧密耦合的子组件应该以父组件名作为前缀命名;

组件名应该倾向于完整单词而不是缩写;

在单文件组件和字符串模板中的组件名应该总是单词首字母大写,但是在DOM模板中总是横线连接的,JS中,单词首字母大写的是类和构造函数;

多个特性的元素应该分多行撰写,每个特性一行。
在这里插入图片描述

《深入浅出Vue.js》已经阅读完成,这本书还是蛮不错的,如果有写的不好的地方,欢迎来讨论

在这里插入图片描述


本文转载自: https://blog.csdn.net/qq_48701993/article/details/126827321
版权归原作者 *neverGiveUp* 所有, 如有侵权,请联系我们删除。

“猿创征文 |《深入浅出Vue.js》打卡Day7”的评论:

还没有评论