Vue基础之插槽、自定义指令、render函数、过滤器

目录

一、插槽

1、默认插槽

2、具名插槽 

3、作用域插槽 

二、自定义指令

三、render渲染函数

四、过滤器 


一、插槽

插槽可以分为默认插槽、具名插槽(具有名字的插槽)、作用域插槽。插槽允许我们在调用子组件的时候为子组件传递模板。

1、默认插槽

没有名字的插槽就是默认插槽,一个不带 name 的 <slot> 出口会带有隐含的名字“default”。

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

组件标签里面的内容会被渲染到默认插槽:

<body>
	<div id="app">
		<!-- 组件标签里面的内容需要使用插槽来接收,否则无法渲染出来,
             而里面的内容会默认渲染到默认插槽中 -->
		<my-a>hello vue</my-a>
	</div>
	<script>
		// 定义组件
		let myA={
			template:`
				<div>
					<p>1111111</p>
					<slot></slot>
                    <slot></slot>
					<p>3333333</p>
				</div>
			`
		}
		new Vue({
			el:"#app",
            //局部注册组件
			components:{
				"my-a":myA
			}
		})
	</script>
</body>

结果如下:

2、具名插槽 

具有名字的插槽就是具名插槽。

当我们需要把组件标签内相应内容渲染到相应的插槽中时,使用具名插槽,此时需要在组件标签内使用template模板:

<slot name='header'></slot>	
<template v-slot:header>头部内容</template>
<body>
	<div id="app">
		<my-a>
			<!-- 使用 v-slot:插槽名 ,这样就可以把相应内容放到相应插槽中 -->
			<template v-slot:footer>底部内容</template>
            <!-- default 表示默认插槽 -->
			<template v-slot:default>hello vue</template>
			<template v-slot:center>中间内容</template>
			<!-- <template v-slot:header>头部内容</template> -->
			<!-- v-slot: 可以简写成 #  -->
			<template #header>头部内容</template>
		</my-a>
	</div>
	<script>
		// 定义组件
		let myA={
			template:`
				<div>
					<p>1111111</p>
					<slot></slot>
                    <slot></slot>
					<p>3333333</p>
					<hr/>
					<slot name='header'></slot>					
					<slot name='center'></slot>					
					<slot name='footer'></slot>	
				</div>
			`
		}
		new Vue({
			el:"#app",
			components:{
				"my-a":myA
			}
		})
	</script>
</body>

结果如下:

3、作用域插槽 

我们在子组件内使用插槽传递数据,传递的数据需要在组件标签内使用作用域插槽获取。

<slot :row='item'></slot>
<template slot-scope="scope">{
   
   {scope}}</template>
<body>
	<div id="app">
		<!-- 父组件给子组件传递数据  :arr="arrs" -->
		<my-a :arr="arrs">
			<!-- v-slot对应插槽的name,这样就可以把相应内容放到相应插槽中 -->
			<template v-slot:footer>底部内容</template>
			<div>hello vue</div>
			<template v-slot:center>中间内容</template>
			<!-- <template v-slot:header>头部内容</template> -->
			<!-- v-slot: 可以简写成 #  -->
			<template #header>头部内容</template>
			<!-- 作用域插槽 slot-scope="变量"  该变量用于接收数据-->
			<template slot-scope="scope">
				{
   
   {scope}}
			</template>
		</my-a>
	</div>
	<script>
		// 定义组件
		let myA={
			// 接收父组件传递过来的数据
			props:['arr'],
			template:`
				<div>
					<p>1111111</p>
					<slot></slot>
					<slot></slot>
					<p>3333333</p>
					<hr/>
					<slot name='header'></slot>					
					<slot name='center'></slot>					
					<slot name='footer'></slot>	
					<hr/>
					<ul>
						<li v-for='item in arr'>
							<slot :row='item'></slot>	
						</li>	
					</ul>	
				</div>
			`
		}
		new Vue({
			el:"#app",
			data:{
				arrs:[
					{id:1,name:'zhangsan'},
					{id:1,name:'lisi'},
					{id:1,name:'wangwu'},
				]
			},
			components:{
				"my-a":myA
			}
		})
	</script>
</body>

结果如下:

可以看到,默认插槽的“hello vue” 没有被渲染出来,因为作用域插槽没有名字,所以也是一个默认插槽。作用域插槽它会将前面的默认插槽内容覆盖,解决办法就是给作用域插槽加上名字:

<slot name="content" :row='item'></slot>	
<!-- v-slot:插槽名字="变量" -->
<template v-slot:content="scope">{
   
   {scope}}</template>

二、自定义指令

Vue中多有的指令都以 v- 来调用。但是,有时候Vue提供给我们的指令并不能满足我们的需求,这个时候 我们就需要自定义指令。

指令允许我们对普通 DOM 元素进行底层操作。可以全局注册也可以局部注册:

全局注册:

Vue.directive()

局部注册:

在Vue实例或组件中添加选项directives

钩子函数:

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。

  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

  • unbind:只调用一次,指令与元素解绑时调用。

钩子函数的参数 有 elbindingvnode 和 oldVnode。

  • el:指令所绑定的元素,可以用来直接操作 DOM。
  • binding:一个对象,包含以下 property:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值
    • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    • expression:字符串形式的指令表达式。
    • arg:传给指令的参数,可选。
    • modifiers:一个包含修饰符的对象。
  • vnode:Vue 编译生成的虚拟节点。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
<body>
	<div id="app">
		<!-- 自定义指令 v-focus  -->
		用户名:<input type="text" v-focus="bgColor">
		<!-- 自定义指令 v-myshow  -->
		<input type="text" v-myshow="msg">
	</div>
	<script>
		// 全局注册自定义指令 Vue.directive('指令名称',{配置对象})
		Vue.directive('focus', {
			inserted(el, binding) {
				// console.log(el,binding);
				// 让输入框自动聚焦
				el.focus()
			},
			// 执行一次性的初始化设置
			bind(el, binding, vnode) {
				console.log(el,binding,vnode);
				el.style.backgroundColor = binding.value
			}
		})
		new Vue({
			// 局部注册自定义指令
			directives:{
				// 指令名称:{配置对象}
				'myshow': {
					bind(el,binding,vnode){
						el.value = binding.value
					}
				}
			},
			el: "#app",
			data: {
				bgColor: 'pink',
				msg: 'hello'
			}
		})
	</script>
</body>

结果如下:
  

参数binding打印结果:

三、render渲染函数

Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。

在定义一个组件的时候,我们一般使用template来创建模板,而使用template来创建模板,最终会被编译成render函数,由render函数来创建一个模板。

例子:

使用template创建模板:

<body>
	<div id="app">
		<my-a></my-a>
	</div>
	<script>
		let myA = {
			template:`
				<div>
					<ul>
						<li v-for='item in arrs'>
							{
   
   {item.name}}	
						</li>	
					</ul>
				</div>
			`,
			data(){
				return {
					msg:"我是一个div标签",
					arrs:[
						{id:1, name:'zhangsan', age:12},
						{id:2, name:'lisi', age:13},
						{id:3, name:'wangwu', age:14},
					]
				}
			}
		}
		new Vue({
			el:"#app",
			components:{
				'my-a': myA
			}
		})
	</script>
</body>

结果:

使用render渲染函数:

<body>
	<div id="app">
		<my-a></my-a>
	</div>
	<script>
		let myA = {
			render(h){
                //遍历创建li标签
				let lis = this.arrs.map(item => {
					return h('li', {}, item.name)
				})
				//三个参数:
				// 第一个参数:创建的标签名称,
				// 第二个参数:一个数据对象,可以设置标签样式、属性等
				// 第三个参数:标签内容,可以写成数组
				return h('ul', {
					style:{
						backgroundColor: 'pink'
					}
				}, lis)
			},
			data(){
				return {
					msg:"我是一个div标签",
					arrs:[
						{id:1, name:'zhangsan', age:12},
						{id:2, name:'lisi', age:13},
						{id:3, name:'wangwu', age:14},
					]
				}
			}
		}
		new Vue({
			el:"#app",
			components:{
				'my-a': myA
			}
		})
	</script>
</body>

 结果如下:

四、过滤器 

Vue.js 允许自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由管道符号 " | " 指示。

全局注册过滤器:

Vue.filter()

局部注册:

在Vue实例或组件中添加选项filters

例子:
使用过滤器处理时间戳和文本:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
	<!-- 引入momentjs -->
	<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
</head>
<body>
	<div id="app">
		<!-- 在插值语法中使用 -->
		{
   
   {time | fmtDate}}
		<!-- 在v-bind中使用 -->
		<div :title="msg | upper">鼠标悬浮查看</div>
	</div>
	<script>
		// 全局注册过滤器 Vue.filter('过滤器名称',过滤器格式处理函数)
		Vue.filter('fmtDate', function(val){
			// 参数val就是需要过滤的值,即管道符前面的值
			// 使用momentjs库将时间戳转换为年月日时分秒 (需要引入monentjs库)
			return moment(val).format('YYYY-MM-DD HH:mm:ss')
		})
		new Vue({
			// 局部注册过滤器
			filters:{
				upper(val){
					// 转成大写
					return val.toUpperCase()
				}
			},
			el:"#app",
			data:{
				time: new Date().getTime(),
				msg: 'hello'
			}
		})
	</script>
</body>
</html>

结果如下:

猜你喜欢

转载自blog.csdn.net/lq313131/article/details/127071958