05 Vue进阶 - 图1


1 slot插槽 (内容分发)

  1. a. 单个slot
  2. b. 具名slot
  3. *混合父组件的内容与子组件自己的模板-->内容分发
  4. *父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。

1.1 基本使用


  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="box">
  10. <!-- 不使用插槽写的aaa不会显示,使用就会显示-->
  11. <child1>aaa</child1>
  12. </div>
  13. </body>
  14. <script>
  15. var bus = new Vue() //new一个vue的实例,就是中央事件总线
  16. Vue.component('child1', {
  17. template: `<div>
  18. 首页
  19. <slot></slot>
  20. </div>`,
  21. })
  22. var vm = new Vue({
  23. el: '#box',
  24. })
  25. </script>
  26. </html>

1.2 插槽应用场景1


  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="box">
  10. <!-- 写了一个轮播组件,用户想轮播什么就放什么-->
  11. <swiper>
  12. <p v-for="data in 4">{{data}}</p>
  13. </swiper>
  14. <swiper>
  15. <img :src="data" v-for="data in 5">
  16. </swiper>
  17. </div>
  18. </body>
  19. <script>
  20. var bus = new Vue() //new一个vue的实例,就是中央事件总线
  21. Vue.component('swiper', {
  22. template: `<div>
  23. <slot></slot>
  24. </div>`,
  25. })
  26. var vm = new Vue({
  27. el: '#box',
  28. })
  29. </script>
  30. </html>

1.3 插槽应用场景2


  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="box">
  10. <!--通过插槽实现在一个组件中控制另一个组件的显示隐藏-->
  11. <navbar> <button @click="isShow=!isShow">点我显示隐藏</button></navbar>
  12. <swiper v-if="isShow"></swiper>
  13. </div>
  14. </body>
  15. <script>
  16. Vue.component('navbar', {
  17. template: `<div>
  18. navbar
  19. <slot></slot>
  20. </div>`,
  21. })
  22. Vue.component('swiper', {
  23. template: `<div>
  24. <p>111</p>
  25. <p>222</p>
  26. <p>333</p>
  27. </div>`,
  28. })
  29. var vm = new Vue({
  30. el: '#box',
  31. data:{
  32. isShow:true
  33. }
  34. })
  35. </script>
  36. </html>

1.4 具名插槽


  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="box">
  10. <!-- 具名插槽,把p标签给a插槽,div标签给b插槽-->
  11. <navbar>
  12. <p slot="a">pppp</p>
  13. <div slot="b">bbbb</div>
  14. </navbar>
  15. </div>
  16. </body>
  17. <script>
  18. Vue.component('navbar', {
  19. template: `<div>
  20. <slot name="a"></slot>
  21. navbar
  22. <slot name="b"></slot>
  23. </div>`,
  24. })
  25. var vm = new Vue({
  26. el: '#box',
  27. data:{
  28. }
  29. })
  30. </script>
  31. </html>

2 transition过渡

  1. Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
  2. (1)单元素/组件过渡 * css过渡 * css动画 * 结合animate.css动画库
  3. (2) 多个元素过渡(设置key)
  4. *当有相同标签名的元素切换时,需要通过 key 特性设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。
  5. mode:in-out ; out-in
  6. (3)多个组件过渡
  7. (4)列表过渡(设置key)
  8. *<transition-group>不同于 transition, 它会以一个真实元素呈现:默认为一个 <span>。你也可以通过tag 特性更换为其他元素。
  9. * 提供唯一的 key 属性值

3 生命周期

  1. i. 生命周期各个阶段https://cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA
  2. ii. 生命周期钩子函数的触发条件与作用

4 swiper学习

https://www.swiper.com.cn/

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/vue.js"></script>
  7. <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
  8. <script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
  9. <!-- <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.css"> -->
  10. <!--<script src="https://unpkg.com/swiper/swiper-bundle.js"> </script> -->
  11. <style>
  12. .swiper-container {
  13. width: 80%;
  14. height: 600px;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <div id="box">
  20. <div class="swiper-container">
  21. <div class="swiper-wrapper">
  22. <div class="swiper-slide" v-for="data in datalist">
  23. {{data}}
  24. <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1608145297276&di=dd396caeaa0bb6a2a50609a109cd3120&imgtype=0&src=http%3A%2F%2Fattachments.gfan.com%2Fforum%2Fattachments2%2Fday_110915%2F1109151356c0717d7e6a91e985.jpg" alt="">
  25. </div>
  26. </div>
  27. <!-- 如果需要分页器 -->
  28. <div class="swiper-pagination"></div>
  29. <!-- 如果需要导航按钮 -->
  30. <div class="swiper-button-prev"></div>
  31. <div class="swiper-button-next"></div>
  32. <!-- 如果需要滚动条 -->
  33. <div class="swiper-scrollbar"></div>
  34. </div>
  35. </div>
  36. </body>
  37. <script>
  38. var vm = new Vue({
  39. el: '#box',
  40. data: {
  41. datalist: [],
  42. },
  43. mounted() {
  44. setTimeout(() => {
  45. this.datalist = ['111', '222', '333']
  46. }, 2000)
  47. //轮播图初始化不是放在这,因为数据变化和dom更新是异步的
  48. //需要放在updated中
  49. },
  50. updated() {
  51. var mySwiper = new Swiper('.swiper-container', {
  52. // direction: 'vertical', // 垂直切换选项
  53. loop: true, // 循环模式选项
  54. // 如果需要分页器
  55. pagination: {
  56. el: '.swiper-pagination',
  57. },
  58. // 如果需要前进后退按钮
  59. navigation: {
  60. nextEl: '.swiper-button-next',
  61. prevEl: '.swiper-button-prev',
  62. },
  63. // 如果需要滚动条
  64. scrollbar: {
  65. el: '.swiper-scrollbar',
  66. },
  67. })
  68. },
  69. })
  70. </script>
  71. </html>

5 自定义组件的封装

自定义封装swiper组件(基于swiper)
注意: 防止swipe初始化过早

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/vue.js"></script>
  7. <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
  8. <script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
  9. <!-- <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.css"> -->
  10. <!--<script src="https://unpkg.com/swiper/swiper-bundle.js"> </script> -->
  11. <style>
  12. .swiper-container {
  13. width: 80%;
  14. height: 600px;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <div id="box">
  20. {{name}}
  21. <!-- diff算法检测到key变化了,会把swipper删掉,重新创建,触发组件的mounted执行,完成swipper实例化,不在updated中初始化-->
  22. <!-- 子组件的mounted在根组件的mounted之前执行,所有组件挂载完成后,根组件才挂载-->
  23. <swipper :key="datalist.length">
  24. <!-- <swipper>-->
  25. <div class="swiper-slide" v-for="data in datalist">
  26. <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1608145297276&di=dd396caeaa0bb6a2a50609a109cd3120&imgtype=0&src=http%3A%2F%2Fattachments.gfan.com%2Fforum%2Fattachments2%2Fday_110915%2F1109151356c0717d7e6a91e985.jpg" alt="">
  27. </div>
  28. </swipper>
  29. </div>
  30. </body>
  31. <script>
  32. Vue.component('swipper',{
  33. template:`
  34. <div class="swiper-container">
  35. <div class="swiper-wrapper">
  36. <slot></slot>
  37. </div>
  38. <div class="swiper-pagination"></div>
  39. <div class="swiper-button-prev"></div>
  40. <div class="swiper-button-next"></div>
  41. <div class="swiper-scrollbar"></div>
  42. </div>
  43. `,
  44. mounted(){
  45. console.log('子组件mounted')
  46. var mySwiper = new Swiper('.swiper-container', {
  47. // direction: 'vertical', // 垂直切换选项
  48. loop: true, // 循环模式选项
  49. // 如果需要分页器
  50. pagination: {
  51. el: '.swiper-pagination',
  52. },
  53. // 如果需要前进后退按钮
  54. navigation: {
  55. nextEl: '.swiper-button-next',
  56. prevEl: '.swiper-button-prev',
  57. },
  58. // 如果需要滚动条
  59. scrollbar: {
  60. el: '.swiper-scrollbar',
  61. },
  62. })
  63. },
  64. // updated(){//如果跟组件中有数据变化,就会导致swipper组件触发update(vm.name='ss'测试一下),导致多次执行,影响效率,所以使用key+mounted方式
  65. // console.log('子组件update')
  66. // var mySwiper = new Swiper('.swiper-container', {
  67. // // direction: 'vertical', // 垂直切换选项
  68. // loop: true, // 循环模式选项
  69. // // 如果需要分页器
  70. // pagination: {
  71. // el: '.swiper-pagination',
  72. // },
  73. // // 如果需要前进后退按钮
  74. // navigation: {
  75. // nextEl: '.swiper-button-next',
  76. // prevEl: '.swiper-button-prev',
  77. // },
  78. //
  79. // // 如果需要滚动条
  80. // scrollbar: {
  81. // el: '.swiper-scrollbar',
  82. // },
  83. //
  84. // })
  85. // }
  86. })
  87. var vm = new Vue({
  88. el: '#box',
  89. data: {
  90. name:'lqz',
  91. datalist: [],
  92. },
  93. mounted() {
  94. setTimeout(() => {
  95. this.datalist = ['111', '222', '333']
  96. }, 2000)
  97. //轮播图初始化不是放在这,因为数据变化和dom更新是异步的
  98. //需要放在updated中
  99. },
  100. })
  101. </script>
  102. </html>

6 自定义指令

  1. (1)自定义指令介绍 directives
  2. (2)钩子函数* 参数 el,binding,vnode(vnode.context)* bind,inserted,update,componentUpdated,unbind
  3. (3)函数简写
  4. (4)自定义指令-轮播
  5. *inserted 插入最后一个元素时调用(vnode.context.datalist.length-1)
  6. *this.$nextTick()

6.1 基本使用


  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="box">
  10. <div v-mystyle>divdiv我是div</div>
  11. </div>
  12. </body>
  13. <script>
  14. //自定义指令,以后用的时候必须 v-指令名,即v-mystyle
  15. Vue.directive('mystyle',{
  16. //当被改指令修饰的标签插入到dom中会执行
  17. inserted(){
  18. console.log('我执行了')
  19. },
  20. })
  21. var vm = new Vue({
  22. el: '#box',
  23. data: {
  24. },
  25. })
  26. </script>
  27. </html>

6.2 让所有使用自定义指令的标签背景都变红色


  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="box">
  10. <div v-mystyle>divdiv我是div</div>
  11. <p v-mystyle>我是p,用了自定义指令,会变红</p>
  12. </div>
  13. </body>
  14. <script>
  15. //自定义指令,以后用的时候必须 v-指令名,即v-mystyle
  16. Vue.directive('mystyle',{
  17. //当被改指令修饰的标签插入到dom中会执行
  18. inserted(el){
  19. //el就是被修饰标签的dom
  20. console.log(el)
  21. //所以我们直接操作dom
  22. el.style.background='red'
  23. },
  24. })
  25. var vm = new Vue({
  26. el: '#box',
  27. data: {
  28. },
  29. })
  30. </script>
  31. </html>

6.3 用户指定自定义指令的背景色,修改变量,背景变化


  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="box">
  10. <!--放js的变量,所以用'red'-->
  11. <div v-mystyle="'red'">divdiv我是div</div>
  12. <p v-mystyle="mycolor">我是p,用了自定义指令,会变红</p>
  13. </div>
  14. </body>
  15. <script>
  16. //自定义指令,以后用的时候必须 v-指令名,即v-mystyle
  17. Vue.directive('mystyle',{
  18. //当被改指令修饰的标签插入到dom中会执行
  19. inserted(el,input){ //该方法,如果更新变量mycolor,并不会变化,所以需要重写update方法 vm.mycolor='yellow'
  20. //el就是被修饰标签的dom
  21. console.log(el)
  22. console.log(input) //input的value属性是传入的变量
  23. //所以我们直接操作dom
  24. // el.style.background='red'
  25. el.style.background=input.value
  26. },
  27. update(el,input){
  28. el.style.background=input.value
  29. }
  30. })
  31. var vm = new Vue({
  32. el: '#box',
  33. data: {
  34. mycolor:'green',
  35. },
  36. })
  37. </script>
  38. </html>

6.4 通过指令控制swipper初始化


  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="js/vue.js"></script>
  7. <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
  8. <script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
  9. <!-- <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.css"> -->
  10. <!--<script src="https://unpkg.com/swiper/swiper-bundle.js"> </script> -->
  11. <style>
  12. .swiper-container {
  13. width: 80%;
  14. height: 600px;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <div id="box">
  20. <div class="swiper-container">
  21. <div class="swiper-wrapper">
  22. <!--v-comp把当前索引值和数组总长度传入,如果索引等于数组总长度减一说明都加载完了,完成swipper初始化-->
  23. <div class="swiper-slide" v-for="(data,i) in datalist" v-comp="{index:i,length:datalist.length}">
  24. {{data}}
  25. </div>
  26. </div>
  27. <!-- 如果需要分页器 -->
  28. <div class="swiper-pagination"></div>
  29. <!-- 如果需要导航按钮 -->
  30. <div class="swiper-button-prev"></div>
  31. <div class="swiper-button-next"></div>
  32. <!-- 如果需要滚动条 -->
  33. <div class="swiper-scrollbar"></div>
  34. </div>
  35. </div>
  36. </body>
  37. <script>
  38. Vue.directive('comp', {
  39. inserted(el, input) {
  40. console.log(input.value)
  41. //只要校验到传入的是最后一个插入了,就初始化swipper
  42. if (input.value.index === input.value.length - 1) {
  43. var mySwiper = new Swiper('.swiper-container', {
  44. // direction: 'vertical', // 垂直切换选项
  45. loop: true, // 循环模式选项
  46. // 如果需要分页器
  47. pagination: {
  48. el: '.swiper-pagination',
  49. },
  50. // 如果需要前进后退按钮
  51. navigation: {
  52. nextEl: '.swiper-button-next',
  53. prevEl: '.swiper-button-prev',
  54. },
  55. // 如果需要滚动条
  56. scrollbar: {
  57. el: '.swiper-scrollbar',
  58. },
  59. })
  60. }
  61. },
  62. })
  63. var vm = new Vue({
  64. el: '#box',
  65. data: {
  66. datalist: [],
  67. },
  68. mounted() {
  69. setTimeout(() => {
  70. this.datalist = ['111', '222', '333']
  71. }, 2000)
  72. },
  73. })
  74. </script>
  75. </html>

7 过滤器

  1. https://cn.vuejs.org/v2/guide/filters.html
  2. ele图片转换,猫眼电影图片转换
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  7. <script src="js/vue.js"></script>
  8. </head>
  9. <body>
  10. <div id="box">
  11. <!--猫眼数据:https://m.maoyan.com/#movie-->
  12. <ul>
  13. <li v-for="data in datalist">
  14. <h2>{{data.nm}}</h2>
  15. <br>
  16. <!-- <img :src="data.img" alt="">-->
  17. <!-- <img :src="changePath(data.img)" alt="">-->
  18. <!-- 过滤器-->
  19. <img :src="data.img | myChange" alt="">
  20. </li>
  21. </ul>
  22. </div>
  23. </body>
  24. <script>
  25. //定义过滤器
  26. Vue.filter('myChange',function (url) {
  27. return url.replace('w.h','128.180')
  28. })
  29. var vm = new Vue({
  30. el: '#box',
  31. data: {
  32. datalist: [],
  33. },
  34. methods:{
  35. changePath(url){
  36. return url.replace('w.h','128.180')
  37. }
  38. },
  39. mounted() {
  40. //http://p0.meituan.net/w.h/movie/b16c1c0d5ac9e743c6ffbbf7eba900522725807.jpg
  41. //http://p0.meituan.net/128.180/movie/b16c1c0d5ac9e743c6ffbbf7eba900522725807.jpg
  42. axios.get("./json/test.json").then(res => {
  43. console.log(res.data.coming) // axios 自动包装data属性 res.data
  44. this.datalist = res.data.coming
  45. }).catch(err => {
  46. console.log(err);
  47. })
  48. },
  49. })
  50. </script>
  51. </html>