1.插槽
普通插槽,具名插槽,作用域插槽
插槽允许我们在调用子组件的时候为子组件传递模板。
<slot> 元素作为承载分发内容的出口。 一个不带 name 的 <slot> 出口会带有隐含的名字“default”。
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
### 1.默认插槽
没有名字的插槽就是默认插槽
<slot>123</slot>
<slot name="default">123</slot>
### 2. 具名插槽
具有名字的插槽
<slot name="slot2">123</slot>
### 3.插槽填充
<my-com>hello</my-com>
内容填充到模板的哪个插槽中?
指定插槽
<my-com>
<template v-slot:default>
hello
</template>
<template v-slot:slot>
123
</template>
<template #slot>
123
</template>
</my-com>
### 插槽声明 {template:`<slot>插槽默认模板</slot>`}
插槽模板
### 1.默认模板
<slot>插槽默认模板</slot>
### 2.自定义模板
<my-com>
<template #name>
插槽自定义模板
</template>
</my-com>
在插槽默认模板中,可以直接访问子组件的数据,可以通过props间接访问父组件的数据
在插槽自定义模板中,可以直接访问父组件的数据,可以通过插槽属性间接访问子组件的数据(插槽作用域)
### html代码 具名插槽有name,可以传值 组件内用<template v-slot:自定义name=‘{传过来的值1,传过来的值2}’>
<div id="app">
<my-com>Hello</my-com>
<my-com>world</my-com>
<!-- 当子组件内什么都没写的时候使用插槽中的默认内容 -->
<my-com></my-com>
<!-- 具名插槽填充 填充默认插槽-->
<my-com>
<template #default>
<div>
123
456
<!-- 模板中使用父组件数据 -->
{{msg}}
</div>
</template>
</my-com>
<!-- 填充指定插槽 作用域插槽 -->
<my-com>
<!-- scope是插槽作用域对象{},内部存放插槽声明时候传递的属性{sub:子组件数据}-->
<!-- <template v-slot:slot2='scope' > -->
<template v-slot:slot2='{sub,test}' >
<div>
<!-- {{scope}} -->
{{sub}}
{{test}}
<p>我是slot2插槽</p>
<h1>hello</h1>
</div>
</template>
</my-com>
</div>
### js代码
Vue.component('my-com',{
data(){
return {
subMsg:'子组件数据'
}
},
template:`
<div>
1012 day04
// 显示子组件内容可以使用插槽 子组件模板内可以直接使用自组建的数据 不能直接使用父组 件的数据
<br>
{{subMsg}}
<button><slot name='default'>默认内容</slot></button>
<div >
<slot name='slot2' :sub='subMsg' :test='1'>默认内容2</slot>
</div>
</div>
`
})
new Vue({
el:'#app',
data:{
msg:'父组件'
}
})
2.动态组件
动态渲染组件
默认情况下,当组件在切换的时候都会重新创建组件,但是有些时候我们希望组件实例能够被在它们第一次被创建的时候缓存下来。为了解决这个问题,我们可以用一个 <keep-alive> 元素将其动态组件包裹起来。
<keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive>
### js代码 js代码可以区分大小写,html里不可区分大小写,则组件命名js代码可以用驼峰命名法,html不行
1.定义组件 2.注册组件 3.使用组件点击后改变显示出来的组件(通过一个变量改变) 4.<keep-alive>包裹动态组件
let myA = {
template: `
<div>
A组件内容
</div>
`,
created() {
console.log('A组件created');
}
};
let myB = {
template: `
<div>
B组件内容
</div>
`,
created() {
console.log('B组件created');
}
};
let myC = {
template: `
<div>
C组件内容
</div>
`,
created() {
console.log('C组件created');
}
};
Vue.component('my-a', myA)
Vue.component('my-b', myB)
Vue.component('my-c', myC)
new Vue({
el: '#app',
data: {
msg: 'hello',
// 可行
// current:myA,
// 可行
current: 'my-a'
},
methods: {}
})
### html代码
<div id="app">
{{msg}}
<button @click="current='my-a'">A组件</button>
<button @click="current='my-b'">B组件</button>
<button @click="current='my-c'">C组件</button>
<!-- 静态is值为注册的组件的名称 -->
<!-- 可行 -->
<!-- <component is="my-a"></component> -->
<!-- 不可行 -->
<!-- <component is="myA"></component> -->
<!-- 不可行 -->
<!-- <component :is="myA"></component> -->
<keep-alive>
<component :is="current"></component>
</keep-alive>
</div>
3.混入
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
1.全局混入
Tip: 不建议使用全局注册混入对象,一旦使用全局混入,它将会影响以后创建的每一个vue实例。
混入规则
当组件和混入对象有同名选项时,这些选项会以恰当的方式合并
-
数据 data 数据对象在混入时,会进行合并,发生冲突是,保留组件的数据 -
值为对象 methods computed等 在混入时,同名的methods会合并成为一个对象,如果对象的键名发生冲突,则保留组件对象的键值对 -
生命周期钩子函数 同名的钩子函数会被合并为一个数组,依次都会被调用,但是混入对象的钩子函数先被调用
### js代码
// 混入(对象)
let mixin = {
// 数据
data() {
return {
mixinData: '混入的数据',
obj: { name: 'zhangsan', gender: '男' }
}
},
// 生命周期
created() {
console.log('混入的created');
},
// 方法
methods: {
mixinMethod() {
console.log('mixinMethod方法');
},
test() {
console.log('test 混入');
}
}
};
// 组件
let myA = {
template: `
<div>
A组件内容
</div>
`,
created() {
console.log('A组件created');
}
};
// 全局混入
Vue.mixin(mixin)
// 全局注册组件
Vue.component('my-a', myA)
let vm = new Vue({
el: '#app',
// 局部混入
// mixins: [mixin],
data: {
msg: 'hello',
obj: { age: 12, name: 'lisi' }
},
created() {
console.log('created...');
},
methods: {
test() {
console.log("test");
}
}
})
### html代码
<div id="app">
{{msg}}
<my-a></my-a>
</div>
4.自定义指令
除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。举个聚焦输入框的例子,当页面加载时,该元素将获得焦点 。事实上,只要在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在可以用指令来实现这个功能 :
### js代码
// 指令对象
let myModel = {
// 绑定的时候调用一次
bind(el, binding, vnode, oldVnode) {
console.log(el, binding, vnode, oldVnode, 'bind...');
},
// 当节点追加到父节点上调用
inserted(el, binding, vnode, oldVnode) {
console.log(el, binding, vnode, oldVnode, 'inserted...');
el.value = binding.value;
el.oninput = function (e) {
// console.log(vnode.context.$root.username);
vnode.context.$root[binding.expression] = e.target.value;
// console.log(vnode.context.$options.username);
}
//在指令钩子函数内如何访问数据模型中的数据
// console.log(this, '---');
},
// vnode更新
update(el, binding, vnode, oldVnode) {
console.log(el, binding, vnode, oldVnode, 'update...');
},
// 组件更新调用
componentUpdated(el, binding, vnode, oldVnode) {
console.log(el, binding, vnode, oldVnode, 'componentUpdated...');
},
// 解绑的时候调用一次
unbind(el, binding, vnode, oldVnode) {
console.log(el, binding, vnode, oldVnode, 'unbind...');
},
};
// 全局注册 v-mymodel
// Vue.directive('mymodel', myModel)
let vm = new Vue({
el: '#app',
components: {},
// 局部注册
directives: {
mymodel: myModel
},
data: {
msg: 'hello',
show: true,
username: 'zhangsan',
},
methods: {
changeUsername(e) {
this.username = e.target.value;
}
},
})
### html代码
<div id="app">
{{msg}}
<!-- <div v-if="show" v-mymodel>{{msg}}</div> -->
{{username}}
<!-- <input @input="changeUsername($event)" type="text" v-mymodel="username"> -->
<input type="text" v-mymodel="username">
</div>
5.过滤器
Vue.js 允许自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”| 符号指示:
<!-- 在双花括号中 --> {{ message | filterMethod }} <!-- 在 `v-bind` 中 -->
首先引入 `moment`第三方库,再进行接下来的操作。引入moment仅供实现功能,与过滤器没有关系。
<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.29.1/locale/af.js"></script>
<script>
// 全局注册
Vue.filter("fmtDate_global", function (date) {
return moment(date).format("YYYY-MM-DD HH:mm:ss");
// 或者return自己编写的时间处理函数
})
new Vue({...})
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello world</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
</head>
<body>
<div id="app">
<!-- 使用过滤器 -->
<div>{{ new Date() | fmtDate_global}}--Ronda</div>
<div :title="new Date() | fmtDate_global">鼠标悬停查看时间</div>
</div>
<script>
// 全局注册过滤器
Vue.filter("fmtDate_global", function (date) {
return moment(date).format("YYYY-MM-DD HH:mm:ss");
// 或者return自己编写的时间处理函数
})
new Vue({
el: '#app',
})
</script>
</body>
</html>
### html代码
<div id="app">
{{msg}} {{msg | parseUpper}}
-----
{{arr}}
<!-- {{arr | parseTime}} -->
<div :title="msg | parseUpper" v-for="item in arr" :key="item.time">
<span>{{item.name}}</span>
<span>{{item.time | parseTime}}</span>
</div>
</div>
### js代码
//以前
/* let arr = [{
name: '',
time: 1600676292941
}, {
name: '',
time: 1600676613869
}, {
name: '',
time: 1600676624202
}];
arr.forEach((item) => {
// item引用数据类型
item.time = parse(item.time);
})
console.log(arr);
function parse(time) {
let date = new Date(time);
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
} */
//全局注册过滤器 {{item.time|parseTime}}
Vue.filter('parseTime', (date) => {
// date就是item.time 2020-09-09 09:09:09 2020/09/09 09:09:09
return new Date(date).toLocaleString();
});
/* Vue.filter('parseUpper', (date) => {
return date.toUpperCase();
}); */
new Vue({
el: '#app',
// 局部注册过滤器
filters: {
parseUpper(date) {
return date.toUpperCase();
}
},
data: {
msg: 'hello',
arr: [{
name: '',
time: 1600676292941
}, {
name: '',
time: 1600676613869
}, {
name: '',
time: 1600676624202
}]
},
methods: {}
})
|