动态组件

什么是动态组件

动态切换组件的显示与隐藏

如何实现动态组件渲染——component组件

vue提供了一个内置的component组件,专门用来实现动态组件的渲染。

  • component组件类似于占位符

is属性的值

  • 表示要渲染组件的名字
  • 组件在components节点下的注册名称。

keep-alive标签

  • 可以把内部的组件进行缓存,而不是销毁组件。
  • 可以保留之前在这个组件上的操作。
  • 对应的生命周期函数:
    • 当组件被缓存时,会自动触发组件的deactivated生命周期函数
    • 当组件被激活时,会自动触发组件的activated生命周期函数
    • 当组件第一次被创建的时候,即执行created也会执行activated
    • 当组件被激活时,只会触发activated,不再触发created,因为组件没有被创建。

可以使用include指定哪些组件需要被缓存,或者使用exclude属性指定哪些组件不需要被缓存,但是不要同时使用include和exclude这两个属性。
include属性:只有名称匹配的组件会被缓存、多个组件之间使用逗号分割
exclude属性:只有名称匹配的组件不会被缓存

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

  1. 组件的注册名称(在components节点下)的主要应用场景是:
    以标签的形式,把注册好的组件,渲染和使用到页面结构中。
  2. 组件声明(定义组件的时候)时候的“name”名称的主要应用场景是:
    结合keep-alive标签实现组件的缓存功能
    在调试工具中看到组件的name名称
<template>
<div>
<keep-alive include="Left">
<component :is="comName"></component>
</keep-alive>
</div>
</template>
data:{
comName:'Left'
},
components:{
Left,
Right
}

插槽

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

基本使用

67b6c08cac6b4f0d8c545d333e2da0f6.png

默认插槽

slot标签

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

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

如果只有一个插槽,一般也会省略name名称。
默认情况下,在使用组件的时候,提供的内容都会被填充到名字为default的插槽之中。

v-slot属性

v-slot只能用于template元素上。

  • 如果要把内容填充到指定名称的插槽中,需要使用v-slot: 这个指令
  • v-slot: 后面要跟上插槽的名字
  • v-slot: 指令不能直接用在元素身上,必须用在template标签上,或者用在一个组件上。
  • template这个标签是一个虚拟的标签,只起到包裹性质的作用,但是不会被渲染为任何实质性的html元素。
  • v-slot: 指令的简写形式是:**#**
<Left>
<template v-slot:default>
<p>这是在Left组件的内容区域,声明的p标签</p>
</template>
</Left>

后备内容

封装组件时,可以为预留的插槽提供后备内容。
如果使用者没有为插槽提供任何内容,则后备内容会生效。

<slot>后备内容</slot>

具名插槽、作用域插槽

具名插槽:为slot插槽指定了name值。
作用域插槽:在封装组件时,为预留的slot标签提供属性对应的值。

//Left组件
<div>
<slot name="content-box"></slot>
</div>
<div>
<slot name="content" msg="helloworld.js" :user="userinfo"></slot>
</div>
data:{
userinfo:{
name:'zs',
age:20
}
}
//使用Left组件
<Left>
<template #content-box="scope">
<div>content-box的内容</div>
<div>{{scope.msg}}</div>
<div>{{scope.user.name}}</div>
</template>
<template #content-box="{msg,user}"> //解构赋值
<div>content-box的内容</div>
<div>{{msg}}</div>
<div>{{user.name}}</div>
</template>
<template #content>
<div>content的内容</div>
</template>
</Left>

约定:一般用一个叫做scope的对象来接收传送过来的值,也可以使用解构赋值来传值。

自定义指令

vue官方提供了v-tex、v-for、v-model、v-if等常用指令,此外,vue还允许开发者自定义指令。

自定义指令分类

私有自定义指令

  • 每个vue组件中,可以在directives节点下声明私有自定义指令。
  • 指令定义的时候不加 v-xxx ,但是使用的时候,需要加上v-xxx
    <div v-xxx></div>

bind函数

当指令第一次被绑定到元素上时,就会立即触发bind函数

  • bind的形参:
    • 第一个形参el:表示当前指令所绑定到的那个DOM对象
    • 第二个形参binding(一般叫做binding):获取指令绑定的值。
      • 在binding对象中:value是程序员可以使用的值,expression的值是用户在等号后写的表达式。
  • bind函数缺点:只在元素第一次绑定到元素上时才会触发,如果DOM更新时,bind函数不会重新执行。

update函数

第一次绑定元素不会调用,但是会在每次DOM更新时被调用。

<div v-color="color">12</div>
<p v-color="'red'">123</p>
data:{
return{
color:blue
}
},
directives:{
color:{
bind(el,binding) {
//binding对象中:value是程序员可以使用的值,expression的值是用户在等号后写的表达式
el.style.color = binding.value;
},
//在DOM更新时调用
update(el,binding){
el.style.color = binding.value;
}
}
}

函数简写:如果bind和update函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式:

//以上代码相当于:
directives:{
color(el,binding) {
el.style.color = binding.value;
}
}

全局自定义指令

  • 全局共享的自定义指令需要通过Vue.directive()进行声明
  • 全局自定义指令要放到main.js文件中
    03b1e683ca50430abb7abe0c1c348264.png

一般来说,定义自定义指令,都是定义全局自定义指令。

ESLint

10561f37113b44cd9d5f2e0cdfb31ac8.png
规则搜索网址:ESLint中文文档

常见错误

443a9135317a47868603d5df4c920c8f.png
43b6cc86c5e54b408f92fe0a441d9b73.png

很好用的插件

6d7676d4bfaa42559c2dfa4770bae1e6.png
配置如下:

// ESLint插件的配置
"editor.codeActionsOnSave": {
"source.fixAll": true
},

93d54fb8eef5475cb0e6caf6e80515b7.png
配置如下:

{
"prettier.configPath": "C:\\Users\\林诗涵\\.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": {
"printWidth": 300,
"trailingComma": "none",
"semi": false,
"singleQuote": true,
"arrowParens": "avoid"
}
},
// ESLint插件的配置
"editor.codeActionsOnSave": {
"source.fixAll": true
},
//导入文件时是否携带文件的扩展名
"path-autocomplete.extensionOnImport": true,
//配置@的路径提示
"path-autocomplete.pathMappings": {
"@": "${folder}/src"
},
"editor.tabSize": 2,
"editor.formatOnSave": true,
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

挂在axios

如果很多.vue组件中要发起请求,每次导入axios会很麻烦,此时可以把axios挂载到Vue的原型上,并配置请求根路径。

方法

在main.js文件中:

  1. 引入axios:import axios from ‘axios’
  2. 全局配置axios的请求根路径:axios.defaults.baseURL = ‘请求根路径’
  3. 把axios挂载到Vue原型上,供每个.vue组件的实例直接调用:Vue.prototype.$http = axios

使用

  • 在某个.vue组件中需要使用axios,就不需要导入,直接调用this.$http.xxx
  • 在某个发送axios请求的组件中就不需要写完整的请求地址了。
    例:this.$http.get('/top/get');

好处:在vue的组件中,使用this.$http就可以发起请求
坏处:不利于API接口的复用

在实际开发中,封装一个request.js模块,创建小axios,并共享出去
7079b9d967044d43965164cccf23c051.png
e5c3299d3a504ed2a62c8e430c9f3b5b.png
request.js内容:
97d317e3d1394b4b8f5d5056f9cde071.png
今后如果要调接口,就导入utils/request.js,就可以得到request实例,也不需要指定根路径,填URL地址即可。(封装API步骤如下)

封装API

  1. 在src目录下新建一个api文件夹,在下面存放封装的api接口
    6964f4e813e0415fa2034a6b9410242d.png
  • 因为API需要发送请求,所以先导入上面封装的utils/request.js
    3ae5be252f074e94bc3af1ef5edcd935.png
  • 向外导出API函数,调用request.xxx方法
  • 一定要把Promise的返回值return出去
  1. 如果需要使用API的话:先导入API,再调用方法(注意点:传参、await、async)
    ca83c91e152a46249e7f880f1d9182d2.png