-
2.5 slot slot-scope
- 具名插槽
- slot-scope
-
2.6 v-slot
- v-slot
-
slot:插槽作用
- 开辟一个空间,给未来元素使用
- 名词解释:未来元素–就是组件内容
注:组件的内容 会被组件模板覆盖 想要这个内容保留下来 就用slot插槽
<div id="app">
<Hello>
<p>这里是组件内容</p>
</Hello>
</div>
<template id="hello">
<div>
<p>这是组件模板</p>
<slot></slot>
</div>
</template>
<script src="../../lib/vue.js"></script>
<script>
Vue.component("Hello",{
template:"#hello"
})
// new Vue({
// el:"#app"//自动挂载
// })
new Vue({
}).$mount('#app') //手动挂载
</script>
具名插槽:
<div id="app">
<Con>
<header slot="heard">头部</header><!--具名插槽 有具体的名子的插槽 -->
<footer>尾部</footer>
</Con>
</div>
<template id="con">
<div>
<slot name="heard"></slot><!--具名插槽 有具体的名子的插槽 -->
<p>这里是中间内容</p>
<slot></slot>
</div>
</template>
<script src="../../lib/vue.js"></script>
<script>
Vue.component("Con",{
template:"#con"
})
new Vue({
el:"#app"
})
</script>
作用域插槽:
<div id="app">
<Con>
<template v-slot:default="info"> <!-- v-slot只能绑定在template标签上 -->
{{info.aa}}
</template>
</Con>
</div>
<template id="con">
<div>
<p>这里是组件模板</p>
<slot :aa="msg"></slot>
</div>
</template>
<script src="../../lib/vue.js"></script>
<script>
// v-slot的目的是将slot组件身上的数据传递给绑定的未来元素
Vue.component("Con",{
template:"#con",
data(){
return{
msg:"这里是数据"
}
}
})
new Vue({
el:"#app"
})
</script>
-
组件的生命周期 【 组件的钩子有哪些? 】
- 为什么要使用生命周期?
- 想要使用组件,那么就得在组件的特定阶段完成特定的任务 【 特定时间点,完成特定任务 】
- 名词: 钩子:
- 钩子:特点时间点,触发的一个方法
组件的生命周期
-
生命周期分为三个阶段:初始化,运行中,销毁,一共8个钩子
-
生命周期钩子不允许使用箭头函数,因为箭头函数会改变this指向
-
初始化 (4个钩子)
-
beforeCreat(){}
-
组件即将创建
-
任务:初始化事件,并为整个生命周期做准备
-
意义:
- 无法获取数据,无法获取的真实的dom
- 可以进行数据请求,和修改数据
-
-
created(){}
- 创建组件结束
- 任务:进行数据的注入和数据的反应(数据反应就是数据的修改)
- 意义:
- 获取到数据,但未获取到真实dom
- 可以进行数据的请求和数据的修改时
-
beforeMount(){}
- 组件即将挂载
- 任务:判断组件是否含有el/template选项,如果含有,直接使用render函数将template模板中的jsx转换成VDOM对象模型,如果没有,需要我们使用$mount(对应el)/outerHTML(对应template)进行手动挂载,–(outerHTML也可以类似于innerHTML作为补办结构书写,但是他会把外层结构消除掉)
- 意义:
- 更多的是内部完成任务,外部就不干预了
- 可以进行数据请求和数据修改
-
mountde(){}
- 组件挂载完成
- 任务:将vdom渲染成真实的dom,然后挂载到页面上,这时候可以在页面中看到内容了
- 意义:
- 拿到真实的dom,操作真实的dom 【可以进行第三方库实例化】
- 可以进行数据请求和数据修改
-
总结:
- 将数据请求放在created里面,因为created是第一次获取到数据的地方
- mounted钩子函数可以进行DOM操作【可以进行第三方库实例化【静态数据】】
-
<div id="app"> <p>{{msg}}</p> </div> <script src="../../lib/vue.js"></script> <script> new Vue({ el:'#app', data:{ msg:'你好 今天周三' }, // 组件即将创建 beforeCreate(){ console.log('1-beforeCreate')//1-beforeCreate console.log(this.msg) //undfined 数据未获取 console.log(document.querySelector('#app')) //<p>{{msg}}</p> 此时是Vdom 真实dom没拿到 fetch('./data/data1.json') .then(res=>res.json()) .then(data=>{ // console.log(data) // console.log(this.msg) //?? this.msg=data.name //?? // console.log(this.msg=data.name) }) .catch(error=> console.log(error)) }, // 组件创建结束 created(){ console.log('2-created') //2-created console.log(this.msg) //拿到数据 console.log(document.querySelector('#app'))//未获得真实dom fetch('./data/data2.json') .then(res=>res.json()) .then(data=>{ // console.log(data) this.msg=data.name }) .catch(error=>console.log(error)) }, beforeMount(){ console.log('3-beforeMount') //3-beforeMount console.log(this.msg) //拿到数据 console.log(document.querySelector('#app'))//未获得真实dom fetch('./data/data2.json') .then(res=>res.json()) .then(data=>{ // console.log(data) this.msg='李四' }) .catch(error=>console.log(error)) }, mounted(){ console.log('4-Mount') //3-beforeMount console.log(this.msg) //拿到数据 console.log(document.querySelector('#app'))//获得真实dom <p>王五</p> 可以操作真实dom // 测试是否可以操作真实dom document.querySelector('p').style.background="red" fetch('./data/data2.json') .then(res=>res.json()) .then(data=>{ // console.log(data) this.msg='王五' }) .catch(error=>console.log(error)) }, // beforeUpdate(){ // // 触发条件 组件数据发生改变 // console.log(this.msg) // console.log('beforeUpdate') // console.log(this.flag)//获取到改变后的数据 // console.log(document.querySelector('#app'))//拿到真实dom // }, }) </script>
- 运行中 (2个钩子)
- beforeUpdate(){} 组件更新之前
- 触发条件:逐渐的数据发生改变(这个数据指的是view层的数据变化 不是data中的数据改变https://www.cnblogs.com/xiaobaibubai/p/8383952.html)
- 任务:VDOM重新生成,然后通过diff算法和以前的VDOM进行比对,生成patch补丁对象【内部进行】
- updated(){} 组件更新之后
- 触发条件:逐渐的数据发生改变(这个数据指的是view层的数据变化 不是data中的数据改变https://www.cnblogs.com/xiaobaibubai/p/8383952.html)
- 任务:将patch补丁对象渲染成真实dom
- 意义:
- 可以操作dom【第三方库的实例化【 动态数据 】】
- 总结: 使用updated进行第三方库实例化
- beforeUpdate(){} 组件更新之前
<div id="app"> <button @click="flag=!flag">确定</button> <p v-if="flag">你好</p><!-- (这个数据指的是view层的数据变化 不是data中的数据改变--> </div> <script src="../../lib/vue.js"></script> <script> new Vue({ el:'#app', data:{ msg:'sss', flag:false }, // mounted(){ // fetch('./data/data2.json') // .then(res=>res.json()) // .then(data=>{ // // console.log(data) // this.msg='王五' // }) // .catch(error=>console.log(error)) // }, beforeUpdate(){ // 触发条件 组件数据发生改变 console.log(this.msg) console.log('beforeUpdate') console.log(this.flag)//获取到改变后的数据 console.log(document.querySelector('#app'))//拿到真实dom }, updated(){ console.log('update') console.log(this.flag)//获取到改变后的数据 console.log(document.querySelector('#app'))//拿到真实dom } }) </script>
-
销毁
-
意义: 用来完成善后工作 【 计时器, 第三库实例, window.onscroll 】
-
组件的销毁有两种形式
- 内部销毁 $destroy
- 组件会被销毁掉,但是组件的DOM外壳还在
<div id="app"> <button @click="remove">销毁</button> </div> <script src="../../lib/vue.js"></script> <script> new Vue({ el: '#app', created(){//组件创建完成 所以都会走这一步 this.dsq=setInterval(()=>{ console.log('hello') //组件和组件的dom都已经销毁了 但是 定时器还在继续执行 所以需要将定时器销毁 },1000) this.obj={ //在内存的堆里开辟一个内存存储这个对象 但是销毁组件时这个内存并没有销毁 所以需要销毁这个内存 name:"sss" } }, methods:{ remove(){ //组件的销毁会触发钩子函数beforeDestroy this.$destroy() //内部销毁 只能销毁组件 但是组件的dom外壳并没有被销毁 } }, beforeDestroy(){ console.log(document.querySelector('#app')) document.querySelector('#app').remove() //删除组件dom外壳 clearInterval(this.dsq)//清除计时器 delete this.obj } }) </script>
- 外部销毁
- 通过开关销毁 【 推荐 】
- 组件会被销毁掉,组件的DOM外壳一起被销毁
<div id="app"> <button @click="flag=!flag">销毁</button><!-- 外部销毁 直接将组件销毁 并且组件的dom一起被销毁 --> <Hello v-if="flag"></Hello> </div> </body> <script src="../../lib/vue.js"></script> <script> Vue.component("Hello",{ template:"<p>你好</p>" , destroyed(){ console.log('destroyed') } }) new Vue({ el: '#app', data:{ flag:true } }) </script>
- 组件的销毁会触发两个钩子函数
- beforeDestroy () {} 销毁前
- destroyed () {} 销毁结束
- 内部销毁 $destroy
-
案例:
1:swiper动态渲染
<link href="https://cdn.bootcss.com/Swiper/4.5.0/css/swiper.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/Swiper/4.5.0/js/swiper.js"></script> <style> .swiper-container { width: 600px; height: 300px; } </style> </head> <body> <div id="app"> <input type="text" name="" id="" v-model="num"> <div class="swiper-container"> <div class="swiper-wrapper"> <div class="swiper-slide" v-for="item in banner" :key="item.id"> <img :src="item.img" style = "width: 100%;height: 100%;"> <!-- 动态数据 --> </div> </div> <!-- 如果需要分页器 --> <div class="swiper-pagination"></div> <!-- 如果需要导航按钮 --> <div class="swiper-button-prev"></div> <div class="swiper-button-next"></div> <!-- 如果需要滚动条 --> <div class="swiper-scrollbar"></div> </div> </div> </body> <script src="../../lib/vue.js"></script> <script> new Vue({ el: "#app", data:{ banner:[], num:12 }, created(){ fetch('./data/data3.json')//fetch异步请求 .then(res=>res.json()) .then(data=>{ this.banner=data console.log(this.banner) console.log(data) }) .catch(error=>console.log(error)) }, updated() {//此时数据是动态的 所以需要使用updated console.log('数据改变 触发updated')//数据改变 触发updated,触发一次updated就会重新实例化mySwiper 消耗性能 // 解决方案1 if(this.mySwiper) return false this.mySwiper = new Swiper('.swiper-container', { //这里获取了真实的dom 能够获取都真实dom有两个钩子 这是上面是动态数据 所以使用updated loop: true, // 循环模式选项 // 如果需要分页器 pagination: { el: '.swiper-pagination', }, // 如果需要前进后退按钮 navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, // 如果需要滚动条 scrollbar: { el: '.swiper-scrollbar', }, }) }, destroyed(){ delete this.mySwiper } }) </script>
2:swiper静态渲染
<link href="https://cdn.bootcss.com/Swiper/4.5.0/css/swiper.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/Swiper/4.5.0/js/swiper.js"></script> <style> .swiper-container { width: 600px; height: 300px; } </style> </head> <body> <div id="app"> <div class="swiper-container"> <div class="swiper-wrapper"> <div class="swiper-slide">Slide 1</div> <div class="swiper-slide">Slide 2</div> <div class="swiper-slide">Slide 3</div><!-- 静态数据 --> </div> <!-- 如果需要分页器 --> <div class="swiper-pagination"></div> <!-- 如果需要导航按钮 --> <div class="swiper-button-prev"></div> <div class="swiper-button-next"></div> <!-- 如果需要滚动条 --> <div class="swiper-scrollbar"></div> </div> </div> </body> <script src="../../lib/vue.js"></script> <script> new Vue({ el: "#app", mounted() {//此时数据是静态的 this.mySwiper = new Swiper('.swiper-container', { //这里获取了真实的dom 能够获取都真实dom有两个钩子 这是上面是静态数据 所以使用mounted loop: true, // 循环模式选项 // 如果需要分页器 pagination: { el: '.swiper-pagination', }, // 如果需要前进后退按钮 navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, // 如果需要滚动条 scrollbar: { el: '.swiper-scrollbar', }, }) }, destroyed(){ delete this.mySwiper } }) </script>
-
5:自定义过滤器
-
注意点:
- 是对已有数据进行格式化
- 过滤器也可以传递参数
- 过滤器要使用管道符才能起作用
-
分类
-
全局过滤器 Vue.filter(过滤器名称,回调函数)
-
局部过滤器 filters选项
filters: { //过滤器名称: 回调函数 'dateFilter': ( val,type) => { var date = new Date( val ) return date.getFullYear() + type + ( date.getMonth() + 1 ) +type+ date.getDate() } }
-
-
使用:
- {{ 要格式化的数据 | 过滤器名称 }}
- | 管道符
- Vue.filter(过滤器名称,过滤器的回调函数 )或者filters:{过滤器名称:过滤器的回调函数 )}
- 注:回调函数中的返回值是什么,格式化后的数据就是什么
局部过滤器
<div id="app">
<p>{{time|dateFilter("-")}}</p>
</div>
<script src="../../lib/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
time:Date.now()//Date.now()时间戳或者 date.getTime()
},
filters:{
"dateFilter":(val,type)=>{
var date = new Date( val ) //val就是要过滤的数据
return date.getFullYear() + type + ( date.getMonth() + 1 ) +type+ date.getDate()
}
}
})
</script>
全局过滤器:
<div id="app">
<p>{{time|dateFilter("-")}}</p> <!--dateFilter("-") 函数的实参 可以没有 -->
</div>
</body>
<script src="../../lib/vue.js"></script>
<script>
Vue.filter("dateFilter",(val,type)=>{//val就是要过滤的数据
var date = new Date( val )
return date.getFullYear() + type + ( date.getMonth() + 1 ) +type+ date.getDate()
})
new Vue({
el:"#app",
data:{
time:Date.now()
}
})
</script>