文章目录
1、自定义指令
1.1自定义指令的钩子函数
bind:
只调用一次,指令第一次绑定到元素时调用,这个钩子函数可以定义在绑定时执行一次的初始化动作。
inserted:
被绑定元素插入父节点时调用(父节点存在即可调用,不必存在document中)。
updated:
所在组件的VNode更新时调用,但是可能发生在其孩子的VNode更新之前,指令的值可能发生了改变也可能没有,但是你可以通过比较更新前后的值来忽悠不必要的模板更新(详细的钩子函数参数见1.2)
componentUpdated:
所在组件的VNode及其孩子的VNode全部更新时调用。
unbind:
只调用一次,指令与元素解绑时调用。
注意区别:
- updated和componentUpdated钩子中不能操作数据源,可以读取,否则会陷入死循环
- bind与inserted:bind时父节点为null,inserted时父节点存在
- update与componentUpdated:update是数据更新前,componentUpdated是数据更新后。
1.2自定义指令钩子函数的参数
el
指令所绑定的元素,可以用来直接操作 DOM。
binding
一个对象,包含指令名称及该指令所绑定的表达式信息。
vnode
Vue 编译生成的虚拟节点。
oldVnode
上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
注意:除了 el 之外,其它参数都是只读的,尽量不要修改他们。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。
2、全局与局部
2.1定义
- 全局:所有组件共同的功能(指令,过滤器,组件)
- 局部:只有当前组件的功能(指令,过滤器,组件)
2.2全局(指令,过滤器,组件)
全局指令
1
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
// 当绑定元素插入到 DOM 中。
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
2
// 注册一个全局自定义指令v-color
<p v-color></p>
<p v-color2="'blue'" ></p>
Vue.directive("color", function (el, obj) {
//el是使用该指令的节点
el.style.color = obj.value || "red";
});
全局过滤器
<p>{{msg|alltool1}}</p>
Vue.filter("alltool1", function (str) {
return str + "-alltool1";
});
全局组件
Vue.component("allbox", {
template: "<div>6666allbox</div>",
});
2.3局部(指令,过滤器,组件)
局部指令
<p v-color></p>
<p v-color2="'blue'" ></p>
directives: {
color2: {
inserted(el, obj) {
el.style.background = obj.value || "red";
},
},
},
局部过滤器
<p>{{msg|box1tool}}</p>
filters: {
box1tool(str) {
return str + "box1-filter";
},
},
局部组件
components: {
Box1: {
template: `<div class="box1">
<p>{{msg|box1tool}}</p>
<p v-color2="'blue'" v-color>{{msg|alltool1}}</p>
<Box11></Box11>
<allbox/>
</div>`,
components: {
Box11: {
template: `<div class="box11">
<h1>box11</h1>
</div>`,
},
},
},
3、nextTick
4、单文件组件
vue create “项目名” ==>下载后启动,就会自己生成vue页面
1、引入:@1官方脚手架 @2挂载vm对象 @3组件引入并渲染到vm中
单文件组件也有全局组件和局部组件,只是把一个组件单独写在一个.vue文件中,供别的组件引入然后注册
2、引入文件时:一般使用相对路径 上一下用…/ 同级使用./ 下级使用/ @ 代表src文件夹
3、注册的组件名不能跟Vue中的和原生DOM的重名,注册的名字是驼峰,使用时就用连字符
4、注册的组件,使用时可以用双标签也可以用单标签:如果有插槽必须使用双标签
5、 如果.Vue的script注释了,在打包的时候Vue的打包环境,会帮我们把这个文件解析为一个对象,然后给这个对象添加一个template属性,值为解析的页面模板,所以.Vue文件中可以没有script,style标签,但是不能没有template(注册组件的时候有就可以了,没有导出语法,加载器 脚手架会去创建对象)
(至少有一个模板或者render函数)
6、不写script标签==>称为静态组件
7、 每一个组件内部只能有一个根元素,不要在根元素上写v-for
8、style标签可以写多个,也可以不写
在项目下创建vue.config.js 就是vue的打包配置文件:
const { defineConfig } = require(‘@vue/cli-service’)
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave:false//关闭eslint的严格模式检测
})
5、组件的属性
属性有两种写法:简单声明和详细描述:
简单声明:
props:[“prop1”,“prop2”]
对属性做详细的描述:props: { propA: Number, // 基础的类型检查 (`null` 匹配任何类型) propB: [String, Number], // 多个可能的类型 propC: { type: String, required: true // 必填的字符串 }, propD: { type: Number, default: 100 // 带有默认值的数字 }, propE: { type: Object, // 带有默认值的对象或者数组填Array default: function () { // 不建议直接填对象(因为对象直接量会一直占用内>存),一般使用工厂函数,调用时才创建对象节省资源(面试) return { message: 'hello' } } }, propF: { validator: function (value) {// 自定义验证函数返回为true就代表数 据符合我们规定 return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } }
1、属性可以多传 但是注册了的属性就必须传 不然有可能会在使用时因为取值问题出BUG
2、属性名不要(不是不能)用vue官方或者原生标签已经签名过的名字:比如id class href
3、属性的类型验证只是一种验证提示 不会阻止程序运行
6、v-slot: 插槽
具名插槽 slot,slot-scope过时了 2.6.0使用v-slot
语法:v-slot:插槽名 语法糖:#插槽名
没有指定插槽名就是默认插入到插槽,不给插槽插入数据的话,就会使用组件的slot中的数据
插槽名不用使用引号引起来,直接写变量名
插入的内容必须是template标签或者组件 不能是原生的元素
//设计组件: .vue组件文件中
<template>
<div class="content1">
<slot></slot>
<slot name="slot1"></slot>
<h1>{{contentData.title}}</h1>
<h2>{{contentData.dt}}</h2>
<slot name="slot3">你不给我数据到3号插槽中 我就会默认显示出来</slot>
<p>{{contentData.text}}</p>
<slot name="slot2"></slot>
</div>
</template>
<script>
export default{
props:{
contentData:{
type:Object,
default:()=>{return {title:"0",dt:"0",text:"0"}}
}
}
}
</script>
//使用组件: .vue页面文件中
<template>
<div>
<content2 :contentData="arr[1]">
<template #slot1>
<img src="../assets/28.jpg">
</template>
<template #slot2>
<p>我在外部插入插槽的数据,不是子组件中的数据,也不是属性传进去的数据</p>
</template>
<template v-slot:slot3>
666
</template>
<p>我并没有指定插入到哪里</p>
</content2>
</div>
</template>
7、css的作用域
局部样式/CSS作用域的实现和原理
1、在style标签中添加一个scoped
2、原理就是vue的插件webpack打包时会:
把当前组件模板中的每一个元素添加一个相同的哈希值命名的属性名
并且为添加了scoped的style中的样式选择器上添加一个属性选择器
4、 scoped: style标签的scoped=“scoped” 生成css的使用作用域只有当前组件内部的选择器生效
5、vue文件中可以出现多个style标签 凡是添加了scoped属性的,里面的选择器就会被修改 没添加scoped属性的就不会被修改
全局样式的写法:1.在.vue文件中的style中写的样式 打包后就是全局样式 2.写一个css文件 在项目中导入就是全局样式
如果全局样式出现了相同的选择器. 就看是哪个最后打包引入项目 哪个的优先级就最高
app.vue
<template>
<div>
<h1 class="apptitle">app组件</h1>
<Box1></Box1>
<Box2></Box2>
</div>
</template>
<script>
//谁先引入,谁先打包,那么后面引入的样式就会显示
import Box2 from "@/components/Box2.vue"
import Box1 from "@/components/Box1.vue"
export default {
components: {
Box1,
Box2
}
}
</script>
<style>
.apptitle{
color: red;
}
</style>
main.js
import Vue from 'vue'
import "./index.css"
import App from './App.vue'
new Vue({
render: h => h(App),
}).$mount('#app')
Box1.vue
<template>
<div>
<h1 class="title">box1页面</h1>
</div>
</template>
<script>
export default {
}
</script>
<style scoped="scoped">
.title{
color: yellow;
}
</style>
8、面试题(组件基础)
组件中的基础语法常见的面试题方向:
7.1 @ 是一个关键字,在引入的文件路径中 它代表src目录
7.2 template:组件的模板中只能有一个根节点
7.3 v-slot: 插槽, 具名插槽 slot,slot-scope过时了 2.6.0使用v-slot
语法:v-slot:插槽名 语法糖:#插槽名
没有指定插槽名就是默认插入到插槽,不给插槽插入数据的话,就会使用组件的slot标签的尖括号中的数据
插槽名不用使用引号引起来,直接写变量名
插入的内容必须是template标签或者组件 不能是原生的元素
7.4 组件的data为什么是个函数然后返回对象,以前使用vm时都是个对象
组件和挂载到界面的vm对象的区别,vm挂载到页面上时,触发了钩子函数的,data生成了,页面上使用的数据就是data容器中渲染上去的,而且页面只有一个vm对象,所以的vm生成完毕(mouted)时data必须存在
组件是引入和注册以后不一定使用的,比如for循环0次就是组件对象生成了的,但是使用0次,所以组件对象并没有使用自己的data容器去渲染数据,造成资源浪费,解决方案就是懒加载:当使用data时去调用,才生成data对象
组件的data 设计成function的用义:组件可以多次使用,每使用一次,函数被调用一次则创建出不同的数据对象,实现同名组件的数据可以相互独立
7.5 scoped: style标签的scoped=“scoped” 生成css的使用作用域只有当前组件内部的选择器生效