Vue 04Day Knowledge Point
一.组件进阶
一.ref 和 $refs
作用:利用 ref 和 $refs 可以用于 获取 dom 元素, 或者组件实例
1.获取原生DOM标签
添加ref属性,获取目标标签


2.通过ref属性获取组件对象
通过 this.$refs 获取组件对象, 可调用组件对象里方法等

二.$nextTick
1.$nextTick的学习
需求:点击改data的数据, 获取原生DOM内容
1.创建标签显示数据
<p ref = "a">数字:{{count}}</p><button @click="btn">点击加一</button>
2.点击+1, 马上获取原生DOM内容
methods: {btn(){this.count++;console.log(this.$refs.a.innerHTML);}}
$nextTick:等DOM更新后, 才会触发执行此方法里的函数体

data改变,更新DOM是异步的,我们可以运用this.$nextTick里的函数体获取到更新后的DOM
2.$nextTick小案例
需求:点击按钮自身隐藏, 出现输入框并马上处于激活状态
注意: 一定要用v-if来写 (保证DOM异步更新前获取不到输入框, 可以体现$nextTick的价值)
<template><!-- 准备好input 和 按钮 --><!-- 按钮点击 会显示 input (点击按钮消失,显示input,并显示focus焦点) --><!-- 给按钮绑定一个点击事件 @click = "searchFn" 然后在methods中 调用事件函数因为input 是进行隐藏 我们使用v-if 按钮则运用v-else 进行一个切换在点击事件函数中 进行v-if="show" 的取反 单点击按钮 按钮隐藏 input框显示--><!-- 获取焦点,就要找dom 给input 添加一个ref 获取dom中的focusthis.$refs.inp.focus()因为他是异步 所以需要用this.$nextTick(()=>{console.log(this.$refs.inp.focus());});--><div><input type="text" placeholder="输入搜索的关键字" v-if="show" ref="inp" /><button v-else @click="searchFn">点击搜索</button></div></template><script>export default {data(){return{show:false,}},methods:{searchFn(){this.show = !this.show;this.$nextTick(()=>{console.log(this.$refs.inp.focus());// console.log(this.$refs.inp);});}}}</script><style></style>
三.dynamic 动态组件
1.基本概念
动态组件:可以改变的组件
动态组件可以解决多组件同一个位置,切换显示的需求
基本语法:
1.compontent 组件(位置) + is属性(哪个组件)

2.修改is属性绑定的值 => 切换组件
3.动态组件切换的时候会销毁
4.可以缓存 keep-alive
2.动态组件点击切换小案例

当点击指定的按钮就会切换相应内容
<template><div><button @click="name = 'little-cat'">小猫</button><button @click="name = 'little-dog'">小狗</button><button @click="name = 'little-pig'">小猪</button><component :is="name"/></div></template><script>import Cat from './components/little-cat.vue';import Dog from './components/little-dog.vue';import Pig from './components/little-pig.vue';export default {data(){return{name:'little-cat'}},components:{'little-cat':Cat,'little-dog':Dog,'little-pig':Pig,}}</script><style></style>
三个子组件都是按照以下代码操作(代码一样,只放一份)
<template>//将小猫改成其他名称 分别放入对于的子组件即可<div><h1>小猫</h1></div></template><script>export default {}</script><style></style>
二.自定义指令
1.自定义指令
自定义指令即自己定义的指令,封装dom操作,扩展额外功能
有局部注册 和 全部注册
需求:当页面加载时,让元素将获得焦点

局部注册
<template><!-- 当我们需要封装dom 扩展额外功能的时候我们就使用自定义指令 --><div><h1 v-color v-backgroundColor v-bold>你好</h1></div></template><script>export default {// 局部注册directives:{"color":{inserted(dom){dom.style.color = 'red';}},"backgroundColor":{inserted(dom){dom.style.backgroundColor = 'yellow';}}}}</script><style></style>
全局注册
// 全局注册// Vue.component("组件标签名",组件对象);// 全局注册 ——自定义属性Vue.directive("bold",{"inserted"(dom){dom.style.fontWeight = 'bold';}})
2.自定义指令的值
语法:在绑定指令时,可以通过“等号”的形式为指令绑定具体的参数值
通过 binding.value 可以拿到指令值,指令值修改会触发 update
<template><!-- 当我们需要封装dom 扩展额外功能的时候我们就使用自定义指令 --><div><!-- 给指定添加颜色 可以 但是不能直接添加 要在数据中传递颜色 然后binding binding.value--><h1 v-color='red' v-bold>你好</h1><h1 v-color='yellow' v-bold>你好</h1><h1 v-color='blue' v-bold>你好</h1><!-- 直接在点击事件赋值是不可以的 需要更新它 --><button @click="red = 'black'">把红色变成黑色</button></div></template><script>export default {data(){return{red:'red',yellow:'yellow',blue:'blue',}},// 局部注册directives:{"color":{inserted(dom,binding){console.log("指令参数",binding);dom.style.color = 'red';// 这里的dom就是我们指令所在的标签的dom 修改dom颜色dom.style.color = binding.value;},// update 会在指令的值v-指令 = "变量" 变量变化时候触发update(dom,binding){dom.style.color = binding.value;}},"backgroundColor":{inserted(dom){dom.style.backgroundColor = 'yellow';}}}}</script><style></style>
三.插槽

1.默认插槽
插槽:组件内部分内容允许外部传入
组件的内容部分,不希望写死,希望能使用的时候自定义,使用插槽。

<template><div class="container"><category-category title="美食" :list="foods"><img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt=""></category-category><category-category title="游戏" :list="games"><ul><li v-for="(g,index) in games" :key="index">{{g}}</li></ul></category-category><category-category title="电影" :list="films"><video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video></category-category></div></template><script>import category from './components/category.-cate.vue'export default {components:{'category-category':category},data(){return{foods:['火锅','烧烤','汉堡','牛排'],games:['lol','穿越火线','QQ飞车','红色警戒'],films:['《蜡笔小新》','《名侦探柯南》','《赌侠》','《赌圣》']}}}</script><style scoped>.container{display: flex;justify-content: space-around;}img{width: 100%;}video{width: 100%;}</style>
<template><div class="category"><h3>{{title}}分类</h3><!-- 定义个插槽 (挖个坑 等着组件的使用者进行填充) --><slot>默认值,当使用者没有传递具体结构,我就出现</slot><!-- <ul><li v-for="(item,index) in list" :key="index">{{item}}</li></ul> --><!-- http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4 --></div></template><script>export default {// props:['list','title']props:['title']}</script><style>.category{background-color: skyblue;width: 200px;height: 300px;}h3{text-align: center;background-color: orange;}</style>
2.具名插槽

<template><div class="container"><category-category title="美食" :list="foods"><img slot="center" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt=""><a slot="footer" href="http://baidu.com">更多美食</a></category-category><category-category title="游戏" :list="games"><ul slot="center"><li v-for="(g,index) in games" :key="index">{{g}}</li></ul><div class="foot" slot="footer"><a href="http://baidu.com">单机游戏</a><a href="http://baidu.com">网络游戏</a></div></category-category><category-category title="电影" :list="films"><video slot="center" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video><!-- <template slot="footer"> --><template v-slot:footer><div class="foot"><a href="http://baidu.com">经典</a><a href="http://baidu.com">热门</a><a href="http://baidu.com">推荐</a></div><h4>欢迎前来观看</h4></template></category-category></div></template><script>import category from './components/category.-cate.vue'export default {components:{'category-category':category},data(){return{foods:['火锅','烧烤','汉堡','牛排'],games:['lol','穿越火线','QQ飞车','红色警戒'],films:['《蜡笔小新》','《名侦探柯南》','《赌侠》','《赌圣》']}}}</script><style scoped>.container,.foot{display: flex;justify-content: space-around;}img{width: 100%;}video{width: 100%;}h4{text-align: center;}</style>
<template><div class="category"><h3>{{title}}分类</h3><!-- 定义个插槽 (挖个坑 等着组件的使用者进行填充) --><slot name="center">默认值,当使用者没有传递具体结构,我就出现1</slot><slot name="footer">默认值,当使用者没有传递具体结构,我就出现2</slot><!-- <ul><li v-for="(item,index) in list" :key="index">{{item}}</li></ul> --><!-- http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4 --></div></template><script>export default {// props:['list','title']props:['title']}</script><style>.category{background-color: skyblue;width: 200px;height: 300px;}h3{text-align: center;background-color: orange;}</style>
3.作用域插槽

<template><div class="container"><category-category title="游戏" ><template scope="obj"><ul><li v-for="(g,index) in obj.games" :key="index">{{g}}</li></ul></template></category-category><category-category title="游戏" ><template scope="obj"><ol><li style="color:red" v-for="(g,index) in obj.games" :key="index">{{g}}</li></ol></template></category-category><category-category title="游戏"><template scope="obj"><h4 v-for="(g,index) in obj.games" :key="index">{{g}}</h4></template></category-category></div></template><script>import category from './components/category.-cate.vue'export default {components:{'category-category':category},}</script><style scoped>.container,.foot{display: flex;justify-content: space-around;}img{width: 100%;}video{width: 100%;}h4{text-align: center;}</style>
<template><div class="category"><h3>{{title}}分类</h3><!-- <slot >默认值,当使用者没有传递具体结构,我就出现1</slot> --><slot :games="games">我是默认的一些内容</slot></div></template><script>export default {props:['title'],data(){return{games:['lol','穿越火线','QQ飞车','红色警戒'],}}}</script><style>.category{background-color: skyblue;width: 200px;height: 300px;}h3{text-align: center;background-color: orange;}</style>
4.插槽传参
匿名插槽传参
<template><div><niming-slot v-slot="obj"><img :src="obj.zidingyi.url" alt=""><h1>{{obj.zidingyi.name}}</h1><h1>{{obj.zidingyi.age}}</h1></niming-slot></div></template><script>import NingMing from "./components/niming-slot.vue";export default {components:{"niming-slot":NingMing,}}</script><style></style>
<template><div><slot :zidingyi="user"></slot></div></template><script>export default {data(){return{user:{name:'小明',age:18, url:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1113%2F041620104229%2F200416104229-8-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1659665716&t=a7f983f36e9540d91b49a362a93540f3",}}}}</script><style></style>
具名插槽传参(需要多个插槽)
<template><div><personal-info><template #header="obj"><h1>{{obj.headerheader}}</h1></template><template #tbody="obj"><h1>{{obj.tbodytbody}}</h1></template><template #footer="obj"><img :src="obj.tupian" alt=""></template></personal-info></div></template><script>import PersonnalInfo from "./components/personal-info.vue"export default {components:{"personal-info":PersonnalInfo,}}</script><style></style>
<template><div><slot name="header" :headerheader="user.name"></slot><slot name="tbody" :tbodytbody="user.age"></slot><slot name="footer" :tupian="user.url"></slot></div></template><script>export default {data(){return{user:{name:'小明',age:18,url:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1113%2F041620104229%2F200416104229-8-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1659665716&t=a7f983f36e9540d91b49a362a93540f3",}}}}</script><style></style>
