vue组件高级用法 - 动态组件&插槽&自定义指令&ESlint

目标:
掌握keep-alive实现组件的缓存:keep-alive标签、include 属性
能够使用插槽提高组件的复用性:slot标签、具名插槽、作用域插槽(接收数据并使用)、后备内容
v-slot指令把内容填充到指定名称的插槽中,只能被用在 组件components 或 template标签
v-slot: 简写 # 如:<template #title></template>

能够知道如何自定义指令:
私有自定义指令directives: { }
全局自定义指令Vue.directive()

了解常见的ESLint语法规则、习惯在ESLint下进行开发
配置VSCode插件及设置,帮助我们规范代码格式,高效开发

动态组件的使用

动态组件指的是动态切换组件的显示与隐藏。实现不同组件的按需展示。

  1. 如何实现动态组件的渲染
    vue提供了一个内置的component组件,作用:组件的占位符。专门用来实现动态组件的渲染。示例代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    data() {
    // 1.当前要渲染的组件名称
    return { comName: 'Left' }
    }
    <! -- 2.通过is属性,动态指定要渲染的组件-->
    <component :is="comName"></component>

    <!-- 3.点击按钮,动态切换组件的名称 -->
    <button @click="comName = 'Left'">展示 Left 组件</button>
    <button @click="comName = 'Right'">展示 Right组件</button>
  2. 内置标签keep-alive – 保持组件的状态
    每次切换组件都是上一个组件被销毁和下一个组件被创建->运行
    如果再次创建同一个组件,它会重新初始化一遍数据,和上一个组件是没有关系的
    如果我们希望切换回来之后原来的数据状态还在,就可以使用keep-alive:防止组件被隐藏的时候被销毁

    1
    2
    3
    <keep-alive>
    <component :is="comName"></component>
    </keep-alive>

    这样隐藏Left的时候不会移除这个组件,而是打上一个inactive标记(被缓存了)(未使用的、不活动的)
    总结:keep-alive可以把内部的组件进行缓存,而不是销毁组件

  3. keep-alive 对应的生命周期函数
    当组件被缓存时,会自动触发组件的deactivated生命周期函数。
    当组件被激活时,会自动触发组件的activated生命周期函数。

  4. keep-alive的include属性 – 指定哪些组件可以被缓存
    只有名称匹配的组件会被缓存

    1
    2
    3
    <keep-alive include="Left,Right">
    <component :is="comName"></component>
    </keep-alive>

    除了include,还有个exclude属性,表示排除项
    注意:这两个属性不能同时使用

    1
    2
    3
    <keep-alive exclude="">
    <component :is="comName"></component>
    </keep-alive>

了解组件 注册名称 和 组件声明时name 的区别

如果在声明组件(定义组件模板结构)的时候,没有为组件指定 name 名称,则组件的名称默认就是“注册时候的名称”。当提供了name属性之后,组件的名称就是name属性的值。

  • 对比(3、4 is my think):
  1. 组件的“注册名称”的主要应用场景是: 以标签的形式,把注册好的组件,渲染和使用到页面结构之中
  2. 组件声明时候的“name”名称的主要应用场景: 结合keep-alive标签实现组件缓存功能;以及在调试工具中看到组件的 name 名称
  3. 一般情况下,注册名称可以将name属性完全替代,不去注册name属性
  4. name属性的独特应用场景:递归组件。指在组件的模板中,使用该组件自身的情况。(这样场景下,注册名称是替代不了name属性的)

开发中,为了标准、方便,建议给每个组件起一个name名称。(虽然我还是不理解除了4的情况有什么必要)

插槽的使用(默认插槽、具名插槽、作用域插槽)

插槽(Slot)是vue为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

在组件的内容节点填写内容,然后把它给渲染出来
image

v-slot指令 – 简写:#

vue官方规定:每一个 slot 插槽,都要有一个 name 名称
如果省略了 slot 的 name 属性,则有一个默认名称叫做 default

默认情况下,在使用组件的时候,提供的内容都会被填充到名字为default的插槽中

1
2
3
4
<Left>
<p>这是在Left组件的内容区域,声明的p标签</p>
<p>这是第二个p标签</p>
</Left>

只有一个插槽的话,name不写也可以

1
2
//Left组件
<slot></slot>

如果要把内容填充到指定名称的插槽中,需要使用v-slot:这个指令 – 简写:#
注意:v-slot指令,只能被用在 组件components 或 template标签
template是个虚拟的标签,只起到一个包裹性的作用,不会被渲染成任何真实的元素

1
2
3
4
5
6
7
8
<Left>
<template v-slot:default>
<p>这是在Left组件的内容区域,声明的p标签</p>
<p>这是第二个p标签</p>
</template>
//或
<template #default>...</template>
</Left>
1
2
// Left组件
<slot name="default"></slot>

插槽的默认内容/后备内容

官方的专业术语:后备内容

1
2
// left组件
<slot name="default"><p>这是default插槽的默认内容</p></slot>

具名插槽

带有名字的插槽就叫做具名插槽。

它也是一个具名插槽,或者叫默认插槽

1
<slot name="default"></slot>

作用域插槽

在预留插槽的时候,声明数据项。在使用的时候可以接收数据并使用:

1
2
3
4
5
// Left
<!-- 在封装组件的时候,为预留的slot提供属性对应的值,这种用法叫做“作用域插槽” -->
<slot name="default" msg="hello vue.js">
<p>这是default插槽的默认内容</p>
</slot>

如果插槽没有声明数据项,则形参scope是个空对象
接收数据的形参建议用 scope(作用域) 来命名

1
2
3
4
5
6
7
// app.vue
<Left>
<template #default="scope">
<p>这是在Left组件的内容区域,声明的p标签</p>
<p>这是第二个p标签 -- {{ scope.msg }}</p>
</template>
</Left>

作用域插槽的解构赋值

1
2
3
4
5
6
<Left>
<template #default="{ msg }">
<p>这是在Left组件的内容区域,声明的p标签</p>
<p>这是第二个p标签 -- {{ msg }}</p>
</template>
</Left>

自定义指令

vue允许开发者自定义指令

vue中的自定义指令分为两类,分别是:

  • 私有自定义指令
  • 全局自定义指令

私有自定义指令

在每个vue 组件中,可以在 directives节点下声明私有自定义指令。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
directives: {
color: {
//为绑定到的 HTML 元素设置红色的文字
bind(el){
// 形参中的 el是绑定了此指令的、原生的DOM对象(固定的写法)
el.style.color = 'red'
}
}
}
// 当指令第一次被绑定到元素上的时候,会立即触发bind方法
<Left v-color></Left>
  • 使用binding.value获取指令绑定的值
1
2
3
4
5
6
7
8
directives: {
color: {
bind(el,binding){ //官方推荐用binding
el.style.color = binding.value;
}
}
}
<Left v-color="'green'"></Left>
  • update函数
    bind函数只调用1次:当指令第一次绑定到元素时调用;当DOM更新时bind函数不会被触发。
    update函数会在每次DOM更新时被调用,绑定的时候不会触发:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
directives: {
color: {
bind(el,binding){
el.style.color = binding.value;
},
//每次DOM更新时被调用,绑定的时候不会触发
update(el,binding){
el.style.color = binding.value;
}
}
}

<h1 v-color="color">APP根组件</h1>
<button @click="color='red'">变成红色</button>
  • 函数简写形式
    如果 bind 和 update 函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式:
1
2
3
4
5
6
directives: {
// 在 bind 和 update 时,会触发相同的业务逻辑
color(el,binding) {
el.style.color = binding.value
}
}

全局自定义指令

和定义过滤器filter一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 参数1: 字符串,表示全局自定义指令的名字
// 参数2: 对象,用来接收指令的参数值
Vue.directive('color',function(el,binding){ //简写形式
el.style.color = binding.value
})

//对象形式:
Vue.directive('color',{ //简写形式
bind(el,binding){
el.style.color = binding.value;
},
update(el,binding){
el.style.color = binding.value;
}
})

ESLint工具

可组装的JS和JSX检查工具 – 约束代码风格
在你的js代码里面 帮你发现问题,并且解决问题

两个中文官网 官网1 官网2

当在项目里面配置了ESLint以后,它就会去检查代码风格,有问题就会报错

  • vscode 设置
    缩进:设置 - 搜索 Editor:Tab Size 设置为2
    保存:设置 - 文本编辑器 - 格式化 - Format on Save(保存时格式化文件)

  • 使用ESLint – 创建新的vue项目
    在选择预设的时候,加上一个Linter / Formatter(默认被选上的)
    然后后面的选项中就多了一项:选择要安装的ESLint的语法规范
    选择倒数第二项 – Standard config 标准配置
    然后选择:
    Lint on save(ctrl s保存的时候进行检查)
    Lint and fix on commit(提交代码的时候进行代码规范的检查,并且把检查到的问题自动修复)
    只勾选第一项默认的就行,第二项不建议勾选。

  • ESLint配置文件 eslintrc.js
    这里是定义的一些规则:

    1
    2
    3
    4
    5
    rules: {
    //固定格式 只在发布阶段会报一个黄色警告,开发阶段不会
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
    }

    我们可以去 官网 的开发文档的规则参考部分来查看这些规则的作用:
    no-console 禁止使用console,no-debugger 禁止使用debugger

ESLint 规则

不符合规则会报对应的错误,以及错误所在的行列数
具体报错规则可以去 ESLint 中文文档 直接搜索

  1. 不能出现连续的空行
  2. 在文件的末尾必须要有空行
  3. 不能有多余的空格
  4. 字符串要用单引号
  5. 对象和属性之间,需要有一个空格分隔
  6. 要求或禁止末尾逗号
  7. 在注释中的 ///* 后强制使用一致的间距

    // 这里是正确注释,//后最少要有一个空格

  8. 强制一致的缩进(该缩进的要缩进,不该缩进的不能缩进)
  9. import导入模块的语句必须声明在文件的顶部
  10. 定义变量而没有使用会报错
  11. 方法的形参之前需要保留一个空格

    show () {} 括号前后都要有一个空格

禁用某规则

如果不想遵守某个规则,和ESLint反着来,可以禁止这个规则
在官方文档中,找到这个规则,会说明如何更改,直接复制想要更改的规则呢么的代码即可
配置如:

1
2
3
4
5
6
7
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
// 在方法的形参 () 之前,是否必须有空格
// always代表需要这个空格,不满足这个规则会报一个warn警告
"space-before-function-paren": ["warn", "always"],
}

注意:只要修改了配置文件,都需要重启服务器

配置VSCode

我们不能保证写的代码完全符合ESLint的要求,所以可以装一些插件,在保存文件的时候自动对文件进行格式化。

  • ESLint插件
    装过之后需要再配置文件中加一下配置项:

    1
    2
    3
    4
    5
    6
    7
    8
    // 设置 -- settingsjson
    // ESLint 插件的配置
    "editor.codeActionsOnSave": {
    // 老师是这样的
    "source.fixAll": true,
    // 搜的一个是这样
    "source.fixAll.eslint": true,
    },
  • Prettier - Code formatter 插件
    C:\Users\lenovo目录下新建.prettierrc配置文件
    填入 {"semi": false, "singleQuote": true, "printWidth": 300, "bracketSpacing": true}
    然后在vscode设置 – settings.json里面添加如下配置:

    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
    "prettier.configPath": "C:\\Users\\lenovo\\.prettierrc",
    "eslint.alwaysShowStatus": true,
    "prettier.trailingComma": "none",
    "prettier.semi": false,
    // 每行文字个数超过此限制将会被迫换行
    "prettier.printWidth": 300,
    // 使用单引号替换双引号
    "prettier.singleQuote": true,
    "prettier.arrowParens": "avoid",
    // 设置vue文件中,HTML代码的格式化插件
    "vetur.format.defaultFormatter.html": "js-beautify-html",
    "vetur.ignoreProjectWarning": true,
    "vetur.format.defaultFormatterOptions": {
    "js-beautify-html": {
    "wrap_attributes": "false"
    },
    "prettier": {
    "trailingComma": "none",
    "semi": false,
    "singleQuote": true,
    "arrowParens": "avoid",
    "printWidth": 300
    }
    },
    // ESLint 插件的配置
    "editor.codeActionsOnSave": {
    "source.fixAll": true
    },
  • 注意点:

    1. 开发哪个项目,就用vscode直接打开该项目目录(保证两个插件能够正常生效)
    2. 在vue文件 – ctrl + s 能够格式化文件

      前提:在.vue文件右键 – 选择“使用..格式化文档/格式化文档的方式” – 点击 配置默认格式化程序,点击 Prettier 将其设置为默认值
      问题:设置默认格式后保存出现逗号的,在setting.json文件中 通过ctrl+f 搜索找到editor.formatOnSave,将其注释就可以解决这个问题

项目初始化

每次新建项目,如果开启了ESLint,一定要进行下面配置,便于我们开发:

  1. 配置默认格式化程序为prettier
    在项目中,任意某文件中 右键 – 使用…格式化文档 – 配置默认格式化程序 – prettier
  2. ESLint配置文件添加配置以下两条规则:
    1
    2
    3
    4
    5
    6
    7
    8
    // .eslintrc.js
    rules: {
    // 方法名 和 括号 之间不强制加空格
    // 注意这里none不是正确的值,应该是never!!!
    'space-before-function-paren': ['warn', 'never'],
    // 组件名可以使用单个单词
    'vue/multi-word-component-names': 0
    }

    关于不符合ESLint格式的显示标记问题,如果我们添加的规则,值的格式错误,或者输入的是没有的值,会不起作用。如none就不是正确的值。

拓展

自定义事件使用$event

内置变量$event,是在我们需要向绑定事件传递参数时候,用来接收事件对象e使用的
@click="add(1,$event)" --- add(n,e){}

只要自定义事件里面接收到的值被覆盖了,就可以考虑使用$event

1
2
3
4
5
6
<Count @num-change="getNewNum(item,$event)"></Count>

// 这里的自定义事件
getNewNum(item,val){
item.goods_count = val;
}

关于main.js中的小提示

main.js的第四行:
Vue.config.productionTip = false
默认是false,改为true会在终端给出一个温馨提示:

1
2
3
You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html

把这句代码删了就相当于是true