vue学习笔记

1.模板语法

  1. 运算表达式
<div id="root">
  {{1+2}}
  {{1>2 ? true : false}}
</div>
  1. v-html 插入html (只用于信任的html, 注意要防止csrf, xss攻击)
<div id="root" v-html="myhtml"></div>
<script>
var vm = new Vue({
  el : "#root",
  data:{
    myhtml:"<a href=javascript:location.href='https://www.baidu.com'>百度</a>"
  }
})
</script>

2.class与style

  1. v-bind:attr="name" 绑定属性
<style>
   .red{
    color:red;
    }
   .yellow{
    color:yellow;
    }
</style>
<div id="root">
  <div v-bind:class="isActive ? 'red' : 'yellow'">phpxxo</div>
  <img v-bind:src="avatar">
</div>
<!-- 简写-->
<div :class="isActive ? 'red' : 'yellow'"></div>
<img :src="avatar">
<script>
var vm = new Vue({
  el : "#root",
  data:{
   isActive:true,
   avatar:"http://www.xxx.jpg"
  }
})
</script>
  1. v-bind:class="className" 类名
<div id="root">
     <!-- 加引号, 表示直接类名 不用在data中定义 -->
     <div v-bind:class="'green'">class1</div>
     <!-- 可简写为:class="" -->
     <div :class="'green'">class2</div>
     <!-- 三目运算写法-->
     <div :class="isActive ? 'red' : 'yellow'">class 三目运算写法</div>
     <!-- 对象写法-->
     <div :class="classObj">class 对象写法</div>
     <!-- 数组写法-->
      <div :class="classArr">class 数组写法</div>
</div>
<script>
var vm = new Vue({
  el:"#root",
  data:{
    // 对象写法, 新增无效 vm.clasObj.classC = true
     classObj:{
             classA:true,
             classB:true
         },
   // 数组写法, 可新增  vm.classArr.push("classC")
     classArr:[
             "classA",
             'classB',
         ]
  }
  }
})
</script>
  1. v-bind:style="xx" style设置
  <div id="root">
        <div :style="isActive ? 'color:red' : 'color:yellow'">style 三目运算</div>
        <div :style="styleObj">style 对象</div>
        <div :style="styleArr">style 数组</div>
        <button @click="changeActive">改变isActive</button>
        <button @click="changeColor">改变字体颜色</button>
    </div>
<script>
 var vm = new Vue({
        el:"#root",
        data:{
           isActive:true, 
           styleObj:{
               fontSize:"18px",
               color:"red"
           },
           styleArr:[
               {fontSize:"18px"},
               {color:"red"}
           ]
        },
        methods:{
            random(min,max){
                return Math.floor(Math.random()*(max-min+1))+min
            },
            changeColor(){
                var colorStr = "RGB(" + this.random(0,255)+","+this.random(0,255)+","+this.random(0,255)+")"
                this.styleObj.color = colorStr
                this.styleArr[1].color = colorStr
            },
            changeActive(){
                this.isActive = !this.isActive
            }
        }
    })
 
</script>

3.条件渲染 v-if v-show

  1. v-if , v-else-if , v-else 动态创建与删除
 <div id="root">
        <ul v-if="dataList.length">
            <li v-for="item in dataList">{{item}}</li>
        </ul>
        <p v-else>空空如也</p>

        <div v-if="which==1">111111111111111</div>
        <div v-else-if="which==2">222222222222222</div>
        <div v-else>333333333333333</div>

        <button @click="setWhich(1)">set which 1</button>
        <button @click="setWhich(2)">set which 2</button>
        <button @click="setWhich(3)">set which 3</button>
        <button @click="changeDataList">changeDataList</button>
    </div>
<script>
    var vm = new Vue({
        el:"#root",
        data:{
           dataList:["php","python","golang"],
           which:1
        },
        methods:{
          setWhich(value){
            this.which = value
          },
          changeDataList(){
            if(this.dataList.length==0)
            {
                this.dataList = ["php","python","golang"]
            }else{
                this.dataList = []
            }
          }
        }
    })
</script>
  1. v-show 动态显示或隐藏
<div id="root">
  <div v-show="isShow"></div>
</div>
<script>
var vm = new Vue({
  el : "#root",
  data:{
    isShow:true  
  }
})
</script>

4.列表渲染

  1. v-for 遍历对象或数组
<div id="root">
       <ul>
             <!-- 遍历数组 -->
           <li v-for="(item,index) in langeList">{{index+1}} {{item}}</li>
           <hr>
           <li v-for="(item,index) of langeList">{{index+1}} {{item}}</li>
       </ul>
       <div>
       </div>
       <div>
        <img v-for="(item,index) in imageList" :src="item" :class="'img'">
        <hr>
        <img v-for="(item,index) of imageList" :src="item" :class="'img'">
      </div>

      <ul>
        <!-- 遍历对象 -->
        <li v-for="(item,key) in userObj">{{key}}: {{item}}</li>
        <hr>
        <li v-for="(item,key) of userObj">{{key}}: {{item}}</li>
      </ul>

    </div>
<script>
    var vm = new Vue({
        el:"#root",
        data:{
            langeList:["php","python","golange"],
            imageList:[
                "https://pic.maizuo.com/usr/movie/73b25044a8c9756fa41d3a723ee6c2c2.jpg?x-oss-process=image/quality,Q_70",
                "https://pic.maizuo.com/usr/movie/294a01da8a6c9ed99bfbaaf52b2e0f25.jpg?x-oss-process=image/quality,Q_70",
                "https://pic.maizuo.com/usr/movie/e004f1cdd920fcb60dfd43f6f19afc2c.jpg?x-oss-process=image/quality,Q_70",
                "https://pic.maizuo.com/usr/movie/428385c8393778d8d75de22434d7ce7d.jpg?x-oss-process=image/quality,Q_70"
             ],
            userObj:{
                username:"phpxxo",
                sex:"2",
                addr:"bj"
            } 
        },
        methods:{
         
        }
    })
 
</script>
  1. v-for 设置key值 设置成后端返回的id , 效率高
   <div id="root">
       <ul>
             <!-- 设置Key值 建议设置成后端返回的id 如果用index效率低 -->
           <li v-for="item in dataList" key="item.id">{{item.username}}</li>
           <button @click="resetData">add item</button>
       </ul>
    </div>
<script>
   var vm = new Vue({
        el:"#root",
        data:{
            dataList:[
                {id:101,username:"xiaofeng"},
                {id:102,username:"xuzhu"},
                {id:105,username:"duanyu"}
            ]
            
        },
        methods:{
            resetData(){
                this.dataList = [
                    {id:101,username:"xiaofeng"},
                    {id:102,username:"xuzhu"},
                    {id:103,username:"jiumozhi"},
                    {id:105,username:"duanyu"}
            ]
          }
        }
    })
 </script>
  1. 数组操作检测
 <div id="root">
       <ul>
           <li v-for="item in dataList" key="item.id">{{item}}</li>
           <!--可以改动数组的-->
           <button @click="push">push</button>
           <button @click="shift">shift</button>
           <button @click="pop">pop</button>
           <button @click="unshift">unshift</button>
           <button @click="splice">splice</button>
           <button @click="reverse">reverse</button>
           <button @click="sort">sort</button>

           <!--下面需要重新赋值-->
           <button @click="concat">concat</button>
           <button @click="slice">slice</button>
           <button @click="map">map</button>
           <button @click="filter">filter</button>

       </ul>
    </div>
<script>
    var vm = new Vue({
        el:"#root",
        data:{
            dataList:[
             1,2
            ]
            
        },
        methods:{
            random(min,max){
                return Math.floor(Math.random()*(max-min+1))+min
            },
            // 改变原数组
            push(){
                this.dataList.push(this.random(1,10))
            },
            pop(){
                this.dataList.pop()
            },
            shift(){
                this.dataList.shift()
            },
            unshift(){
                this.dataList.unshift(this.random(1,10))
            },
            reverse(){
                this.dataList.reverse()
            },
            sort(){
                this.dataList.sort()
            },
            splice(){
                this.dataList.splice(1,1,this.random(1,10))
            },

            // 不改变原数组,需要重新赋值
            concat(){
                this.dataList = this.dataList.concat([6,7,8])
            },
            slice(){
                this.dataList = this.dataList.slice(0,3)
            },
            map(){
                this.dataList = this.dataList.map(function(val){
                    return "m_" + val
                })
            },
            filter(){
                this.dataList = this.dataList.filter(function(val){
                    if(val>5) return true
                })
            }
        }
    })
 </script>
  1. Vue.set() 修改数组或对象
    <div id="root">
       <ul>
           <li v-for="(item,index) of dataList">{{item}}</li>
           <!--数组操作 下标操作法不能被捕捉-->
           <button @click="arrsetIndex">arrsetIndex</button>
           <!--splice , Vue.set() 解决更新某个下标元素-->
           <button @click="arrSplice">arrSplice</button>
           <button @click="arrVueSet">arrSet</button>
           
           <!--对象操作 下标操作法不能被捕捉-->
           <li v-for="(item,key) of userinfo">{{key}}: {{item}}</li>
           <button @click="objsetIndex">objsetIndex</button>
           <!--Vue.set() 解决-->
           <button @click="objVueSet">objVueSet</button>

       </ul>
    </div>

<script>
    var vm = new Vue({
        el:"#root",
        data:{
            dataList:["js","jq"],
            userinfo:{
                username:"phpxxo",
                age:18
            }
            
        },
        methods:{
            // 数组
            arrsetIndex(){
                this.dataList[1] = "vue"
            },
            arrSplice(){
                this.dataList.splice(1,1,"vue")
            },
            arrVueSet(){
                Vue.set(this.dataList,1,"vue")
            },
            // 对象
            objsetIndex(){
                this.userinfo.username = "vue"
            },
            objVueSet(){
                Vue.set(this.userinfo,"addr","bj")
            }
           
        }
    })
 
</script>
  1. 列表过滤数据 搜索-filter
  <div id="root">
        <input type="text" v-model="title" @input="handlerTitle">
        <ul>
            <li v-for="item in dataList">{{item}}</li>
        </ul>
    </div>

<script>
   var vm = new Vue({
        el:"#root",
        data:{
            title:"",
            odataList:["abc","bcd","aa","bb","cc","ac","aab"],
            dataList:[],
        },
        methods:{
            init(){
                this.dataList = this.odataList
            },
            handlerTitle(){
                // this.dataList = this.odataList.filter(item=>{
                //     return item.indexOf(this.title) > -1
                // })
                
                // 箭头函数简写
                this.dataList = this.odataList.filter(item=>item.indexOf(this.title)>-1)
            }

        },
        created:function(){
           this.init();
        }
    })


</script>

5.事件

  1. v-on:event="func" 绑定事件
<div id="root">
  <button v-on:click="submit">click1</button>
  <button @click="submit">click2</button>
</div>
<script>
var vm = new Vue({
  el:"#root",
  data:{},
  methods:{
    submit(){
      alert("submit")
  }
  }
})
</script>
  1. 事件处理器
   <div id="root">
        <!--直接写代码逻辑-->
        <button @click="alert(msg)">click1</button>
        <!--不需要传参数 不加()-->
        <button @click="fn1">click2</button>
        <!--需要传参数 加()-->
        <!--这里传msg就是data中的msg-->
        <button @click="fn2(msg)">click3</button>
    </div>

<script>
    var vm = new Vue({
        el:"#root",
        data:{
            msg:"你好!"
        },
        methods:{
            fn1(){
                alert(this.msg)
            },
            fn2(msg){
                alert(msg)
            }
        }
    })
</script>

3.事件修饰符

<script>
/*
    *   self, 只触发自己身上的事件(阻止冒泡)
    *   prevent,  阻止默认行为, 例a标签, 表单submit事件
    *   stop, ($event) (阻止冒泡)
    *   once  只执行一次
*/
</script>

    <div id="root">
     <!--只有在ul上的点击才触发-->
      <ul @click.self="clickUl">
          <!--阻止冒泡, 不传递到ul-->
          <li @click.stop="clickLi" v-for="item of dataList">100</li>
      </ul>

      <a href="https://www.baidu.com">百度</a>
      <!--通过event阻止打开链接-->
      <a href="https://www.baidu.com" @click="stopTarget($event)">百度</a>
      <!--通过vue事件修饰符.prevent 阻止打开链接-->
      <a href="https://www.baidu.com" @click.prevent>百度</a>
      <!--once 只执行一次, 下面第一次点击不打开链接, 第二次能打开链接-->
      <a href="https://www.baidu.com" @click.once="stopTarget($event)">百度</a>
    </div>

<script>
    var vm = new Vue({
        el:"#root",
        data:{
            dataList:[100,101,102]
        },
        methods:{
          clickUl(){
              alert("clickUl")
          },
          clickLi(){
              alert("clickLi")
          },
          stopTarget(event)
          {
            event.preventDefault();
          }
        }
    })
</script>
    

4.按键修饰符

   <div id="root">
        <form @submit.prevent>
            <!--传统的方式 处理器中判断keyCode-->
            <input type="text" name="title" @keyup="hand($event)">
            <!--vue的按键修饰符 处理更为简单-->
            <input type="text" name="nick" @keyup.enter="submit">
              <!--不知道单词, 可以写成keyCode数字-->
              <input type="text" name="nick" @keyup.13="submit">

        </form>
    </div>

<script>
var vm = new Vue({
    el:"#root",
    data:{

    },
    methods:{
        hand(event){
            console.log('run hand')
            if(event.keyCode == 13)
            {
                alert("submit")
            }
        },
        submit(){
            alert("submit")
        }
    }
})
</script>

6. 表单控件绑定 v-model

1.表单双向绑定 字符串跟布尔值

   <div id="root">
        <form>
            <input type="text" v-model="form.username">
            <span>{{form.username}}</span>
            <br><br>
            <input type="checkbox" v-model="form.remember">记住密码
        </form>
    </div>

<script>
var vm = new Vue({
    el:"#root",
    data:{
        form:{
            username:"",
            remember:false,
        }
    },
    methods:{
     
    }
})
</script>

  1. 表单绑定 值为数组
<div id="root">
    <form>
        <input type="text" v-model="form.username">
        <br>性别:
                <label>
                <input type="radio" value="2" name="sex" v-model="form.sex">男
                </label>
                <label>
                <input type="radio" value="3" name="sex" v-model="form.sex">女
            </label>
        <br>
            <label>
            <input type="checkbox"  name="langgroup"  value="php"  v-model="form.langgroup">php
            </label>
            <label>
            <input type="checkbox"  name="langgroup"  value="javascript" v-model="form.langgroup">javascript
            </label>
            <label>
            <input type="checkbox"  name="langgroup" value="python" v-model="form.langgroup">python
            </label>

    </form>
</div>

<script>
var vm = new Vue({
    el:"#root",
    data:{
        form:{
            username:"",
            remember:false,
            sex:"",
            langgroup:[]
        }
    },
    methods:{
     
    }
})
</script>

  1. 购物车
<!---1.总价计算-->
<div id="root">
    <ul>
        <li v-for="item in shopcar">{{item.goods_name}}   ({{item.price}}/件 * {{item.num}} = {{item.num*item.price}} )  <button @click="addGoods(item.id)">+</button> <button @click=reduceGoods(item.id)>-</button></li> 
        <span>一共是<span style="color:red"> ¥{{totalPrice}}</span></span>
    </ul>
</div>

<script>
   var vm = new Vue({
        el:"#root",
        data:{
            goodsList:[
                {id:100,goods_name:"一号",price:10.6,image:"http://vue.com/images/1.jpg"},
                {id:101,goods_name:"二号",price:1.6,image:"http://vue.com/images/2.jpg"},
                {id:102,goods_name:"三号",price:15,image:"http://vue.com/images/3.jpg"},
                {id:103,goods_name:"三号",price:20,image:"http://vue.com/images/4.jpg"}
            ],
            shopcar:[
                {id:100,goods_name:"一号",num:1,price:10.6,image:"http://vue.com/images/1.jpg"},
                {id:101,goods_name:"二号",num:10,price:1.6,image:"http://vue.com/images/2.jpg"},
                {id:102,goods_name:"三号",num:2,price:15,image:"http://vue.com/images/3.jpg"},
                {id:103,goods_name:"三号",num:4,price:20,image:"http://vue.com/images/4.jpg"}
            ],
            form:{
                username:"",
                remember:false,
                sex:"",
                langgroup:[]
            }
        },
        methods:{
            addGoods(id){
               for(var index in this.shopcar){
                   if(this.shopcar[index].id == id)
                   {
                       this.shopcar[index].num++
                   }
               }
            },
            reduceGoods(id){
                for(var index in this.shopcar){
                   if(this.shopcar[index].id == id)
                   {
                       if(this.shopcar[index].num!=0) {
                            this.shopcar[index].num--
                       }
                       
                   }
               }
            }
        },
        computed:{
            totalPrice(){
               var total = 0 
               for(var index in this.shopcar){
                  total += this.shopcar[index].price*this.shopcar[index].num
               }
               return total
            }
        }
    })
</script>


<!--2.商品增减 传参改为item对象-->
<div id="root">
    <ul>
        <li v-for="item in shopcar">{{item.goods_name}}   ({{item.price}}/件 * {{item.num}} = {{item.num*item.price}} )  <button @click="addGoods(item)">+</button> <button @click=reduceGoods(item)>-</button></li> 
        <span>一共是<span style="color:red"> ¥{{totalPrice}}</span></span>
    </ul>
</div>

<script>
   var vm = new Vue({
        el:"#root",
        data:{
            goodsList:[
                {id:100,goods_name:"一号",price:10.6,image:"http://vue.com/images/1.jpg"},
                {id:101,goods_name:"二号",price:1.6,image:"http://vue.com/images/2.jpg"},
                {id:102,goods_name:"三号",price:15,image:"http://vue.com/images/3.jpg"},
                {id:103,goods_name:"三号",price:20,image:"http://vue.com/images/4.jpg"}
            ],
            shopcar:[
                {id:100,goods_name:"一号",num:1,price:10.6,image:"http://vue.com/images/1.jpg"},
                {id:101,goods_name:"二号",num:10,price:1.6,image:"http://vue.com/images/2.jpg"},
                {id:102,goods_name:"三号",num:2,price:15,image:"http://vue.com/images/3.jpg"},
                {id:103,goods_name:"三号",num:4,price:20,image:"http://vue.com/images/4.jpg"}
            ],
            form:{
                username:"",
                remember:false,
                sex:"",
                langgroup:[]
            }
        },
        methods:{
            addGoods(item){
                item.num ++
            },
            reduceGoods(item){
                if(item.num!=0){
                   item.num -- 
                }
            }
        },
        computed:{
            totalPrice(){
               var total = 0 
               for(var index in this.shopcar){
                  total += this.shopcar[index].price*this.shopcar[index].num
               }
               return total
            }
        }
    })
</script>

<!--3.增加checkbox 选择商品订单及全选-->
<div id="root">
    <style>
        ul li{
            list-style-type:none;
        }
    </style>
    <input type="checkbox" v-model="allChecked" @change="handleChange">全选
    <ul>
        <li v-for="item in goodsList">
            <input type="checkbox" :value="item" v-model="shopcar" @change="handleLiChange">
            {{item.goods_name}}   ({{item.price}}/件 * {{item.num}} = {{item.num*item.price}} )  <button @click="addGoods(item)">+</button> <button @click=reduceGoods(item)>-</button></li> 
        <span>一共是<span style="color:red"> ¥{{totalPrice}}</span></span>
    </ul>
</div>

<script>
   var vm = new Vue({
        el:"#root",
        data:{
            goodsList:[
                {id:100,goods_name:"一号",num:1,price:10.6,image:"http://vue.com/images/1.jpg"},
                {id:101,goods_name:"二号",num:10,price:1.6,image:"http://vue.com/images/2.jpg"},
                {id:102,goods_name:"三号",num:2,price:15,image:"http://vue.com/images/3.jpg"},
                {id:103,goods_name:"三号",num:4,price:20,image:"http://vue.com/images/4.jpg"}
            ],
            shopcar:[],
            allChecked:false,
           
        },
        methods:{
            addGoods(item){
                item.num ++
            },
            reduceGoods(item){
                if(item.num!=0){
                   item.num -- 
                }
            },
            handleChange(){
               if(this.allChecked){
                   this.shopcar = this.goodsList
               }else{
                  this.shopcar = []
                  
               }
               
            },
            handleLiChange(){
                if(this.shopcar.length == this.goodsList.length){
                   this.allChecked = true
               }else{
                   this.allChecked = false
               }
            }

        },
        computed:{
            totalPrice(){
               var total = 0 
               for(var index in this.shopcar){
                  total += this.shopcar[index].price*this.shopcar[index].num
               }
               return total
            },

        }
    })
</script>

7.表单修饰符

1.表单修饰符 lazy, number, trim

  <div id="root">
        <!--表单输入变动就会同步绑定数据-->
        <input type="text" v-model="form.title"> {{form.title}}
        <br>
        <!--表单修饰符 lazy 表示光标离开才同步绑定数据, 可提高性能-->
        <input type="text" v-model.lazy="form.name"> {{form.name}}
        <!--表单修饰符 number-->
        <br>
        <input type="text" v-model.lazy.number="form.num">{{form.num}}
        <!--用html type=numer-->
        <br>
        <input type="number">
        <br>
        <input type="text" v-model.trim="form.username">#{{form.username}}#
      
    </div>

<script>
    var vm = new Vue({
        el:"#root",
        data:{
            form:{
                title:"",
                name:"",
                num:0
            }
        },

    })
</script>

8.http请求

  1. fetch请求
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>http请求fetch</title>
    <script src="./js/vue-2.6.js"></script>
    <style>
        li img{
            width:30px;
            height:30px;
        }
    </style>
</head>
<body>
    <div id="root">
        <ul>
            <li v-for="item in goodsList">{{item.goods_name}} <img :src="item.image"></li>
        </ul>
    </div>
</body>

<script>
    // http协议
    const request = {
        url:"./data/goods.json"
    }
    const headers = new  Headers({
        'Access-Control-Allow-Origin':'*',
        "Content-Type":'text/plain'
    })
   
    var vm = new Vue({
        el:"#root",
        data:{
            goodsList:[]
        },
        methods:{
            initGoodsList(){
               that = this 
               fetch(request.url,{
                    method: "GET",
                    headers: headers,
                    mode: "no-cors",
                    
               })
               .then(function(res){
                   console.log(res)
                   return res.json()
                })
               .then(function(res){
                  console.log(res) 
                  that.goodsList = res

               })
              
               
            }
        },
        created(){
            this.initGoodsList()
        }
    })
</script>

2.axios 插件请求

 <style>
        li img{
            width:30px;
            height:30px;
        }
    </style>

  <div id="root">
        <ul>
            <li v-for="item in goodsList">{{item.goods_name}} <img :src="item.image"></li>
        </ul>
    </div>

<script>
    // http协议
    const request = {
        url:"./data/goods.json"
    }
   
    var vm = new Vue({
        el:"#root",
        data:{
            goodsList:[]
        },
        methods:{
            initGoodsList(){
               axios.get(request.url)
                .then(res=>{
                   // 箭头函数, 这里this指vm
                   this.goodsList = res.data
                })
                .catch(error=>{
                   console.log(error) 
                })
               
            }
        },
        created(){
            this.initGoodsList()
        }
    })
</script>

9. 计算属性 computed

computed中的状态只要改变, 就会重新计算
1.computed 基本使用

 <div id="root">
        <div>{{name.substring(0,1).toUpperCase()+name.substring(1)}}</div>
        <!--看控制台运行结果可看-->
        <!--计算属性 多处使用 只计算一次-->
        <div>{{getName}}</div>
        <div>{{getName}}</div>

        <!--方法 多处使用 -->
        <div>{{getNameMethod()}}</div>
        <div>{{getNameMethod()}}</div>
    </div>

<script>
    var vm = new Vue({
        el:"#root",
        data:{
            name:"jack"
        },
        methods:{
            getNameMethod(){
                console.log("getNameMethod")
                return this.name.substring(0,1).toUpperCase()+this.name.substring(1)
            }
        },
        computed:{
            getName(){
                console.log("getName")
                return this.name.substring(0,1).toUpperCase()+this.name.substring(1)
            }
        }
       
    })
</script>

2.计算属性computed 模糊查询

  <div id="root">
        <input type="text" v-model="title">
        <ul>
            <li v-for="item in getDataList">{{item}}</li>
        </ul>
    </div>

<script>
    var vm = new Vue({
        el:"#root",
        data:{
            title:"",
            odataList:["abc","bcd","aa","bb","cc","ac","aab"],
        },
        computed:{
            getDataList(){
                return this.odataList.filter(item=>item.indexOf(this.title)>-1)
            }
        }
    })
</script>

10.组件

1.全局组件

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>全局组件要点</title>
    <script src="./js/vue-2.6.js"></script>
    <style>
        .actived{
            color:red;
        }
    </style>
</head>
<body>
    <div id="root">
       <tabs></tabs>
       <test></test>
    </div>
</body>
<script>
    /*
     全局组件要点:
     1.定义用 Vue.component
     2.全局组件在任何组件中可以使用
    */
    Vue.component("tabs",{
        template:`<div>
            <ul>
                <li @click="handlerClick('home')" :class="{actived:curr=='home'}">home</li>
                <li @click="handlerClick('cat')"  :class="{actived:curr=='cat'}">cat</li>
                <li @click="handlerClick('user')" :class="{actived:curr=='user'}">user</li>
            </ul>
        </div>`,
        data(){
           return {
               curr:"home"
           }
        },
        methods:{
            handlerClick(name){
                this.curr = name
            }
        }
    })

    Vue.component("test",{
        template:`<div>
            <tabs></tabs>
        </div>`
    })
    var vm = new Vue({
        el:"#root",
        
    })
</script>

2.局部组件

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>局部组件要点</title>
    <script src="./js/vue-2.6.js"></script>
    <style>
        .actived{
            color:red;
        }
    </style>
</head>
<body>
    <div id="root">
       <test></test>
    </div>
</body>
<script>
    /*
     局部组件要点:
     1.定义在子组件中 用components
     2.局部组件在哪个组件中定义的, 就只能在哪个组件中使用
    */
    Vue.component("test",{
        template:`<div>
            <tabs></tabs>
        </div>`,
        // 定义局部组件
        components:{
            tabs:{
                template:`<div>
                <ul>
                    <li @click="handlerClick('home')" :class="{actived:curr=='home'}">home</li>
                    <li @click="handlerClick('cat')"  :class="{actived:curr=='cat'}">cat</li>
                    <li @click="handlerClick('user')" :class="{actived:curr=='user'}">user</li>
                </ul>
                </div>`,
                data(){
                return {
                    curr:"home"
                }
                },
                methods:{
                    handlerClick(name){
                        this.curr = name
                    }
                }
            }
        }
    })
    var vm = new Vue({
        el:"#root",
        
    })
</script>
  1. 组件与Vue实例编写区别
<script>
   /*
        组件与Vue实例编写区别:
        1. 自定义组件必须有一个root element包起来
        2. 组件的data 定义是一个函数, 返回一个对象
        3. 父子组件data无法共享
    */
</script>
  <div id="root">
        <child></child>
        <hr>
        <div>
            <input type="text" v-model="username">
            <span style="color:red;">{{username}}</span>
            <br>
            <button @click="reset">reset</button>
        </div>
    </div>

<script>
 
    Vue.component("child",{
        template:`<div>
        <input type="text" v-model="title">
        <span style="color:red;">{{title}}</span>
        <br>
        <button @click="reset">reset</button>
        </div>`,
        data(){
            return {
               title:""
            }
        },
        methods:{
            reset(){
                this.title = ""
            }
        }
    })

    var vm = new Vue({
        el:"#root",
        data:{
            username:""
        },
        methods:{
            reset(){
                this.username = ""
            }
        }
    })
</script>

11. 组件通信

  1. 父传子
  <div id="root">
        <!--传字符串参数-->
        <child  msg="parent"></child>
        <!--传状态-->
        <child :msg="parent"></child>
        <!--这么传false会当成字符串-->
        <child  isshow="false"></child>
        <!--绑定参数 false会当成布尔值-->
        <child  :isshow="false"></child>
    </div>

<script>
    /*
       要点: 
       1.子组件中props数组中定义 要接收的参数名
       2.父组件写子组件标签, 参数名="值" , 如果是传父组件中的状态, 用:参数名="xx" 绑定
       3.子组件模板中 使用参数名
       4.注意如果要传布尔值, 用绑定方式, 否则传false会当成字符串, 变成真
    */
    Vue.component("child",{
        template:`<div>
            <div>{{msg}}</div>
            <div v-show="isshow">123</div>
        </div>`,
        // 接受参数 , 注不要写驼峰
        props:["msg","isshow"]
        
    })

    var vm = new Vue({
        el:"#root",
        data:{
           parent:"这是父组件中的parent"
        }
       
    })
</script>

2.属性验证 定义属性类型

  <div id="root">
        <!--如果vue是开发版, 定义了属性验证, 传入值类型不对, 控制台会报错-->
        <child  isshow="false"></child>
        <child  :isshow="false"></child>
        
    </div>

<script>
    /*
     要点:
     1.vue.js是开发版 才有效
     2.props 定义为对象, key为属性名, 值为类型, null表示不限制类型
    */
    Vue.component("child",{
        template:`<div>
            <div>{{msg}}</div>
            <div v-show="isshow">123</div>
        </div>`,
        // 参数修饰符
        props:{
            msg:null,
            title:String,
            isshow:Boolean
        }
        
    })

    var vm = new Vue({
        el:"#root",
        data:{
         
        }
       
    })
</script>

3.子传父

    <div id="root">
        <div v-show="isshow">phpxxo</div>
        <child @channel_msg="channelHandle($event)"></child>
    </div>

<script>
    /*
    要点:
        1.父组件通过 @channel_name 监听, 等号后是事件处理器,如果要接受参数括号中传$event  例: <navbar @channel_name="eventHandle($event)"
        2.子组件通过 this.$emit("myevent","参数") 发送事件消息
        注意:channel_name 不要用驼峰命名
   
    */
    Vue.component("child",{
        template:`<div>
           <div>this is child</div>
           <button @click="sendHideMsg">隐藏父级phpxxo</button> 
          
        </div>`,
        // 参数修饰符
        methods:{
            sendHideMsg(){
                this.$emit("channel_msg","123")
            }
        }
        
    })

    var vm = new Vue({
        el:"#root",
        data:{
            isshow:true
        },
        methods:{
            channelHandle(event){
                alert(event)//123
                this.isshow = !this.isshow
            }
        }
       
    })
</script>

4.ref 通信

  <div id="root">
        <!--ref绑在元素上, 获取到dom节点-->
        <input type="text" ref="input_title">{{form.title}}
        <br>
        <button @click="getTitle">getTitle</button>
        
        <br>
        <!--ref绑在组件上, 获取到组件-->
        <child ref="my_child"></child>
        <button @click="handleChild">handleChild</button>
    </div>

<script>
    Vue.component("child",{
        template:`
           <div v-show="isshow">child</div>
        `
        ,
        data(){
            return {
                isshow:true
            }
        },
        methods:{
            sayMsg(msg){
                alert(msg)
            }
        }

    })

    var vm = new Vue({
        el:"#root",
        data:{
           form:{
             title:""
           }
        },
        methods:{
            getTitle(){
                console.log(this.$refs.input_title)//得到input原生对象
                console.log(this.$refs.input_title.value)//得到value值
                this.form.title = this.$refs.input_title.value
            },
            handleChild(){
                // 得到child组件
                var child = this.$refs.my_child
                console.log(child)
                // 操作组件状态
                child.isshow = !child.isshow
                // 调组件方法
                child.sayMsg('粑粑')

            }
           
        }
    })
</script>

5.子组件之间用父组件搭线通信

 <div id="root">
     <childa @chan_1="sendb"></childa>
     <childb ref="childb"></childb>
    </div>

<script>
    Vue.component("childa",{
        template:`
           <div>
            <span>childa</span>
            <button @click="send">通知父组件控制childb</button>
           </div>
           
        `
        ,
        data(){
            return {
                isshow:true
            }
        },
        methods:{
          send(){
              this.$emit("chan_1")
          }
        }
    })

    Vue.component("childb",{
        template:`
           <div v-show="isshow">childb</div>
        `
        ,
        data(){
            return {
                isshow:true
            }
        }
       
    })

    var vm = new Vue({
        el:"#root",
        data:{
          
        },
        methods:{
            sendb(){
               this.$refs.childb.isshow = !this.$refs.childb.isshow
            }
           
        }
    })
</script>

6.事件总线

  <div id="root">
     <childa></childa>
     <childb></childb>
    </div>

<script>
    /*
        事件总线所有组件共用, 独立存在, 所有组件可以跟它互相通信
        事件总线用法:
        1.先实例化无参数Vue var bus = new Vue()
        2.在组件中监听总线事件 bus.$on("myevent",callback)
        3.发送消息  bus.$emit("myevent")
    */
    // 中央事件总线 
    var bus = new Vue()

    Vue.component("childa",{
        template:`
           <div>
            <span>childa</span>
            <input type="text" ref="mytext">
            <button @click="send">控制childb</button>
           </div>
           
        `
        ,
        data(){
            return {
                isshow:true
            }
        },
        methods:{
          send(){
              // 操作childb
              bus.$emit("myevent",this.$refs.mytext.value)
          }
        }
    })

    Vue.component("childb",{
        template:`
           <div v-show="isshow">childb</div>
        `
        ,
        data(){
            return {
                isshow:true
            }
        },
       // dom渲染完调用, 它的调用时机晚于created
       mounted(){
           bus.$on("myevent",(msg)=>{
                this.isshow = !this.isshow
                alert(msg)
           })
       }

    })

    var vm = new Vue({
        el:"#root",
        data:{
          
        }
    })
</script>
  1. 动态组件与keep-alive
 <style>
        .current{
            background-color: red;
        }
    </style>

   <div id="root">
    <tabs @myevent="handler"></tabs>   
     <!--keey-alive 保留组件状态,避免重新渲染-->
     <keep-alive>
        <!--component 动态的绑定多个组件到它的is属性 is写的哪个, 生效的就是哪个-->
        <component :is="who"></component>
    </keep-alive>
    </div>

<script>
    Vue.component("tabs",{
        template:`
        <footer>
            <ul>
                <li @click="change('home')" :class="{current : who == 'home'}">home</li>
                <li @click="change('cate')" :class="{current : who == 'cate'}">cate</li>
                <li @click="change('user')" :class="{current : who == 'user'}">user</li>
            </ul>
        </footer>`,
        data(){
            return {
                who:"home"
            }
        },
        methods:{
            change(currentWho){
                this.who = currentWho
                this.$emit("myevent",this.who)
            }
        }
    
    })

    var vm = new Vue({
        el:"#root",
        data:{
          who:"home"
        },
        // 动态组件
        components:{
            home:{
                template:`<div>home
                <input type="text"></div>`
            },
            cate:{
                template:`<div>cate
                <input type="text"></div>`
            },
            user:{
                template:`<div>user
                    <input type="text"></div>`
            }
        },
        methods:{
            handler(currentWho){
                this.who = currentWho
            }
        }
    })
</script>

8.插槽 slot

   <div id="root">
        <child>
          <!--插槽绑定的事件 事件处理器, 状态 访问域在父组件-->
          <button @click="say(msg)">say</button>
        </child>
    </div>

<script>
 
    var vm = new Vue({
        el:"#root",
        data:{
            msg:"haha"
        },
        methods:{
            say(msg){
                  alert(msg)
              }
        },
        components:{
           child:{
                template:`
                  <div>
                     <slot></slot>
                  </div>
                `
           }
           
        }
       
    })
</script>

  1. 具名插槽
 <div id="root">
        <child>
            <li>111</li>
            <li>222</li>
            <li>333</li>
        </child>

        <childtwo>
            <li slot="a">aaa</li>
            <li slot="c">ccc</li>
            <li slot="b">bbb</li>
        </childtwo>
    </div>

<script>
    // 具名插槽 就是给slot起名字, 定义slot时定义name="xxx" , 插入时可指定slot="xx" , 可以有顺序的插入
    var vm = new Vue({
        el:"#root",
        data:{
        
        },
        components:{
           child:{
                template:`
                <ul>
                    <slot></slot>
                </ul> `
           },
           childtwo:{
                template:`
                    <ul>
                        <slot name="a"></slot>
                        <slot name="b"></slot>
                        <slot name="c"></slot>
                    </ul> `
            }

        }
       
    })
</script>

12.组件生命周期8个钩子方法

 <style>
        /*
        1.beforCreate  组件刚创建,未完成所有初始化,data状态没有
        2.created      组件创建初始化完成 data准备好

        3.beforMount  组件挂载前
        4.mounted     组件挂载后

        5.beforUpdate 更新前
        6.updated     更新后

        7.beforDestroy  销毁组件时前调用 (该方法需要定义在对应的组件中)
        8.destroyed     销毁组件后调用   (该方法需要定义在对应的组件中)
        */
    </style>

  <div  id="root">
    </div>

<script>
    let consoleLog = console.log
    console.log = function (msg){
       consoleLog("%c "+msg,"color:red")
    }


    Vue.component("child",{
        template:`
        <div>
           child
        </div>
        `,
        beforeDestroy(){
            console.log("child beforeDestroy")
        },
        destroyed(){
            console.log("child destroy")
        }

    })
    var vm = new Vue({
        el:"#root",
        template:
        `
        <div>
            <div v-show="isshow">来日方长</div>
            <child v-if="iscreated"></child>
            <button v-on:click="isshow=!isshow">update</button>
            <button v-on:click="iscreated=!iscreated">destroy</button>
        </div>
        `,
        
        data:{
            isshow:true,
            iscreated:true
        },
        methods:{
          
        },
        // 组件实例刚创建,未初始化所有,  data属性计算之前
        beforeCreate()
        {
        
            console.log("beforCreate",this.isshow) //beforCreate undefined
        },
        // 组件实例初始化完, data已有, dom未创建 
        created(){
            console.log("created",this.isshow)//created true
        },
        // 模板编译, 挂载之前
        beforeMount(){
            console.log("beforeMount")
        },
        // 模板编译, 挂载之后
        mounted(){
            console.log("mounted")
        },
        // 组件更新前
        beforeUpdate(){
            console.log("beforeUpdate")
        },
        // 组件更新后
        updated(){
            console.log("updated")
        },
        // 组件销毁前
        beforeDestroy(){
            console.log("beforeDestroy")
        },
        // 组件销毁后 
        destroyed(){
            console.log("destroy")
        }

    })

</script>

13.动画

1.单个元素过渡-原生

  <style>
        .myleave{
            transition:all 3s;
            opacity: 0;
            transform:translateX(100px)
        }
        .myenter{
            transition:all 3s;
        }
       
    </style>

 <div id="root">
       
             <div  :class="isShow== true ? 'myenter' : 'myleave'">my name is phpxxo</div>
      
        <br>
        <button @click="change">button</button>
    </div>
    <script>
        var vm = new Vue({
            el:"#root",
            data:{
                isShow:true
            },
            methods:{
                change(){
                    this.isShow = !this.isShow
                }
            }
        })

    </script>

2.单个元素过渡-vue

 <style>
        
        /*
        enter-active 进入过程
        leave-active 离开过程
        */
        .mydh-enter-active, .mydh-leave-active{
            transition:all 1s;
           
        }
        /*
         enter 进入前
         leave-to 离开后
        */
        .mydh-enter,.mydh-leave-to{
            opacity:0;
            transform:translateX(100px);
        }

    </style>

  <div id="root">
            <transition name="mydh">
                 <div v-show="isShow">my name is phpxxo</div>
            </transition>
        <br>
        <button @click="isShow = !isShow">button</button>
    </div>
    <script>
        var vm = new Vue({
            el:"#root",
            data:{
                isShow:true
            },
            methods:{
              
            }
        })

    </script>

3.单个元素过渡-光键帧动画定义

 <style>

      /*
       进入时
      */
      .bounce-enter-active{
        animation:bounce-in 1s; 
      }
      /*
      离开时
      */
      .bounce-leave-active{
        animation:bounce-in 1s reverse;
      }

      /*
      过渡控制
      */
      @keyframes bounce-in{
        0%{
            opacity:0;
            transform:translateX(100px)
        }
        100%{
            opacity:1;
            transform:translateX(0px)
        }
      }

    </style>

 <div id="root">
            <transition name="bounce">
                 <div v-show="isShow">my name is phpxxo</div>
            </transition>
        <br>
        <button @click="isShow = !isShow">button</button>
    </div>
    <script>
        var vm = new Vue({
            el:"#root",
            data:{
                isShow:true
            },
            methods:{
              
            }
        })

    </script>

4.多个元素过渡

  <style>
        /*
        多个元素过渡, 指的是多个元素显示切换动画效果
        1.设置不同的值的key(推荐), 或用不同元素标签
        2.mode 设置的值有 out-in , in-out 
        */
        .bounce-enter-active{
            animation:bounce-in 1s;
        }
        .bounce-leave-active{
            animation:bounce-in 1s reverse;
        }

        @keyframes bounce-in{
            0%{
                opacity:0;
                transform:translateX(100px)
            }
            100%{
                opacity:1;
                transform:translateX(0px)
            }
        }
    </style>

<div id="root">
        <transition name="bounce" mode="out-in">
            <div v-if="isshow" key="1">111</div>
            <div v-esle="isshow" key="2">222</div>
        </transition>
        <button @click="isshow = !isshow">点我</button>
    </div>
    <script>
        var vm = new Vue({
            el:"#root",
            data:{
                isshow:true
            }
        })
    </script>

5.多个组件过渡

<style>
       .current{
           background-color: red;
       }

       .bounce-enter-active{
           animation:bounce-in 1s;
       }
       .bounce-leave-active{
           animation:bounce-in 1s reverse;
       }

       @keyframes bounce-in{
           0%{
               opacity:0;
               transform:translateX(100px)
           }
           100%{
               opacity:1;
               transform:translateX(0px)
           }
       }

   </style>

<div id="root">
   <tabs @myevent="handler"></tabs>   
    <!--keey-alive 保留组件状态,避免重新渲染-->
    <keep-alive>
       <!--component 动态的绑定多个组件到它的is属性 is写的哪个, 生效的就是哪个-->
       <transition name="bounce" mode="out-in">
            <component :is="who"></component>
       </transition>
   </keep-alive>
   </div>
</body>
<script>
   Vue.component("tabs",{
       template:`
       <footer>
           <ul>
               <li @click="change('home')" :class="{current : who == 'home'}">home</li>
               <li @click="change('cate')" :class="{current : who == 'cate'}">cate</li>
               <li @click="change('user')" :class="{current : who == 'user'}">user</li>
           </ul>
       </footer>`,
       data(){
           return {
               who:"home"
           }
       },
       methods:{
           change(currentWho){
               this.who = currentWho
               this.$emit("myevent",this.who)
           }
       }
   
   })

   var vm = new Vue({
       el:"#root",
       data:{
         who:"home"
       },
       // 动态组件
       components:{
           home:{
               template:`<div key="1">home
               <input type="text"></div>`
           },
           cate:{
               template:`<div key="2">cate
               <input type="text"></div>`
           },
           user:{
               template:`<div key="3">user
                   <input type="text"></div>`
           }
       },
       methods:{
           handler(currentWho){
               this.who = currentWho
           }
       }
   })
</script>

6.列表过渡

 <style>
        .bounce-enter-active{
            animation:bounce-in 1s;
        }
        .bounce-leave-active{
            animation:bounce-in 1s reverse;
        }
        @keyframes bounce-in{
            0%{
                opacity:0;
                transform:translateX(100px);
            }
            100%{

            }
        }

    </style>
 <div id="root">
        <transition-group name="bounce" tag="span">
            <li v-for="(item,index) in dataList" :key="item.id">
                {{item.username}}
                <button @click="del(item.id)">del</button>
            </li>
        </transition-group>
        <input type="text" v-model="mytext">
        <button @click="add">add</button>
    </div>

<script>
    var vm =new Vue({
        el:"#root",
        data:{
            mytext:"",
            dataList:[
                {id:101,username:"xiaofeng"},
                {id:102,username:"xuzhu"},
                {id:105,username:"duanyu"}
            ]
        },
        methods:{
            del(id) { 
                console.log(id)
               for(let i=0; i<this.dataList.length;i++){
                   if(this.dataList[i].id == id){
                      this.dataList.splice(i,1)
                   }
               }
            },
            add(){
                var obj = {
                    id:Date.parse(new Date()),
                    username:this.mytext
                }
                this.dataList.push(obj)
            }
        }
    })
</script> 

7.可复用过渡

 <style>
        ul{
            background:yellow;
            width:200px;
        }
        .bounce-enter-active{
            animation:bounce-in .3s;
        }
        .bounce-leave-active{
            animation:bounce-in .3s reverse;
        }
        @keyframes bounce-in{
            0%{
                opacity:0;
                transform:translateX(-100%);
            }
            100%{
                opacity:1;
                transform:translateX(0px);
            }
        }
    </style>

<div  id="root">
    <navbar @chan="myHandle"></navbar>
    <transition name="bounce">
            <sidebar v-show="isshow"></sidebar>
    </transition>
</div>

<script>

    Vue.component("navbar",{
        template:`
            <div>
                <button @click="sendMsg">click</button>
            </div>
        `,
        methods:{
            sendMsg(){
                this.$emit("chan")
            }
        }
    })


    Vue.component("sidebar",{
        template:`
            <div>
                <ul>
                    <li v-for="item in dataList">{{item}}</li>
                </ul>
            </div>
        `,
        data:function(){
            return {
                dataList:[
                    "php","js","python"
                ]
            };
        },
        methods:{
            sendMsg(){
                this.$emit("chan")
            }
        }
    })
    

    var vm = new Vue({
        el:"#root",
        data:{
            isshow:true
        },
        methods:{
            myHandle(){
                this.isshow = !this.isshow
            }
        }
    })

</script>

14.vue中使用swiper

  1. swiper-轮播 简单使用
<style>
        /*
        swiper轮播基本使用
        一. 引入插件资源 swiper.min.css , swiper.min.js
        二. 定义html
        1.定义插件容器 <div class="swiper-container">
        2.定义插件包裹容器 <div class="swiper-wrapper">
        3.在swiper-wrapper容器中定义轮播项
        4.定义其它需要的功能
         <!-- 如果需要分页器 -->
            <div class="swiper-pagination"></div>
            <!-- 如果需要导航按钮 -->
            <div class="swiper-button-prev"></div>
            <div class="swiper-button-next"></div>
            <!-- 如果需要滚动条 -->
         <div class="swiper-scrollbar"></div>
        5.实例化Swiper
         var mySwiper = new Swiper ('.swiper-container', {})
            
        */
        .swiper-container {
            width: 750px;
            height: 300px;
        }
    </style>

 <div id="app">
        <div class="swiper-container">
            <div class="swiper-wrapper">
                <div class="swiper-slide"><img src="./images/banner/1.jpg"></div>
                <div class="swiper-slide"><img src="./images/banner/2.jpg"></div> 
                <div class="swiper-slide"><img src="./images/banner/3.jpg"></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>

    <script>
            var mySwiper = new Swiper ('.swiper-container', {
           // direction: 'vertical', // 垂直切换选项
            loop: true, // 循环模式选项

            // 如果需要分页器
            pagination: {
                  el: '.swiper-pagination',
            },

            // 如果需要前进后退按钮
            navigation: {
                nextEl: '.swiper-button-next',
                prevEl: '.swiper-button-prev',
            },

            // 自动播放
            autoplay: {
                delay: 2500,//延期时间
                disableOnInteraction: false,
            },

            // 如果需要滚动条
            scrollbar: {
            el: '.swiper-scrollbar',
            },
            })        
    </script>

2.swiper-轮播 使用动态数据

  <style>
        .swiper-container{
            width:750px;
            height:300px;
        }
    </style>

 <div id="app">
        <div class="swiper-container">
            <div class="swiper-wrapper"></div>
              <!-- 如果需要分页器 -->
              <div class="swiper-pagination"></div>
        </div>

    </div>

    <script>
        setTimeout(function(){
            var data = [
                "./images/banner/1.jpg",
                "./images/banner/2.jpg",
                "./images/banner/3.jpg"
            ];
            // var dataList = data.map(item=>{
            //   return  ` <div class="swiper-slide"><img src="${item}"></div>`
            // })

            var dataList = data.map(item=>
               ` <div class="swiper-slide"><img src="${item}"></div>`
            )
            console.log(dataList)
            document.querySelector(".swiper-wrapper").innerHTML = dataList.join('');
            new Swiper(".swiper-container",{
            loop:true,
            // 如果需要分页器
            pagination: {
                  el: '.swiper-pagination',
            },
            // 如果需要前进后退按钮
            navigation: {
            nextEl: '.swiper-button-next',
            prevEl: '.swiper-button-prev',
            },
            // 如果需要滚动条
            scrollbar: {
                  el: '.swiper-scrollbar',
            },
            autoplay:{
                delay:3000,
                disableOnInteraction: false,
            }
        })
        },500)
        
    </script>

3.vue结合swiper

<style>
    .swiper-container{
        width:750px;
        height:300px;
    }
</style>

 <div id="app">
        <div class="swiper-container">
           <div class="swiper-wrapper">
               <div class="swiper-slide" v-for="data in dataList"><img :src="data"></div>
            </div>
             <!-- 如果需要分页器 -->
             <div class="swiper-pagination"></div>
        </div>
    </div>

<script>
    // 定义资源请求地址
    const Request= {
        url:"./data/banner.json"
    }
    var vm = new Vue({
        el:"#app",
        data:{
            dataList:[],
        },
        methods:{
            // 初始化swiper
            initSwiper(){
                new Swiper(".swiper-container",{
                    loop:true,
                    autoplay:{
                        delay:3000,
                        disableOnInteraction: false,
                    },
                    pagination:{
                       el:".swiper-pagination"
                    }
                })
            }
        },
        mounted(){
            axios.get(Request.url)
            .then(res=>{
               if(res.data.status == 0) {
                    alert("接口出错")
               }
               this.dataList = res.data.data
            console.log(res.data)
            })
            .catch(error=>{
                 alert(error)
            })
          
        },
        updated(){
            this.initSwiper()
        }
    })
  
        
</script>

  1. vue 组合swiper 封装成组件
 <script src="./js/swiper.min.js"></script>
 <script src="./js/vue.dev.js"></script>
 <script src="./js/axios.js"></script>

<style>
    .swiper-container{
        width:750px;
        height:300px;
    }
    /*
        核心:
        1.组件swiper定义插槽, 具体内容由root组件插入
        2.swiper组件 定义:key="dataList.length" 当dataList发生改动, 这样就重新挂载swiper组件, 
        就会自动调用swiper中的mounted方法, 在该方法中完成实例化Swiper轮播
        */
</style>

   
<div id="app">
    <!--swiper组件-->
    <swiper :key="dataList.length">
        <!--swiper组件插槽-->
        <div v-for="data in dataList" class="swiper-slide"><img :src="data"></div>
    </swiper>
</div>

<script>
    // 定义资源请求地址
    const Request= {
        url:"./data/banner.json"
    }

    // swiper组件
    Vue.component("swiper",{
        template:`
        <div class="swiper-container">
           <div class="swiper-wrapper">
             <slot></slot>
            </div>
            <div class="swiper-pagination"></div>
        </div>
        `,
        methods:{
             // 初始化swiper
             initSwiper(){
                new Swiper(".swiper-container",{
                    loop:true,
                    autoplay:{
                        delay:3000,
                        disableOnInteraction: false,
                    },
                    pagination:{
                       el:".swiper-pagination"
                    }
                })
            }
        },
        mounted(){
            console.log("swiper mounted")
            this.initSwiper()
        }

    })

    var vm = new Vue({
        el:"#app",
        data:{
            dataList:[],
        },
        methods:{
           initDataList(){
                axios.get(Request.url)
                .then(res=>{
                if(res.data.status == 0) {
                        alert("接口出错")
                }
                this.dataList = res.data.data
                console.log(res.data)
                })
                .catch(error=>{
                    alert(error)
                })
           }
        },
        mounted(){
            console.log("mounted")
            this.initDataList()
          
        },
        updated(){
           console.log("updated")
        }
    })
  
        
</script>

15.vue指令

1.指令基本使用

<style>
    /*
      指令基本使用
      第一步:定义指令
      Vue.redirective("指令名",{
        // el可以获取到原生DOM, 通过bind.value可以接收指令调用传的参数
        inserted(el,bind){}, // 插入父节点后执行
        update(el,bind){} // 状态改变执行
      })
      
      第二步:实例化vue 
      var vm = new Vue({
        el:"#app"
      })

      第三步:在标签上使用自定义指令
      v-指令名="参数"
      参数可以是任一类型

    */
  </style>

<body>
  <div id="app">
    <div v-hello></div>
    <div v-bgcolor="'red'">111</div>
    <div v-bgcolor="'blue'">111</div>
    <div v-bgcolor="color">111</div>
    <button @click="color = 'yellow'">selected yellow</button>
  </div>
</body>
<script>
  Vue.directive("hello", {
    inserted(el, bind) {
      el.innerHTML = "hello"
    }
  })

  Vue.directive("bgcolor", {
    // 插入到父节点后执行
    inserted(el, bind) {
      el.style.backgroundColor = bind.value
    },
    // 状态更新执行
    update(el, bind) {
      el.style.backgroundColor = bind.value
    }

  })
  var vm = new Vue({
    el: "#app",
    data: {
      color: "red"
    }
  })


</script>

2.$nextTick方法

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>this.$nextTick</title>
  <script src="./js/vue.dev.js"></script>
  <link type="text/css" rel="styleSheet" href="./css/swiper.min.css">
  <script src="./js/swiper.js"></script>
  <style>
    /*
      this.$nextTick() 方法,执行比updated还要晚, 能确保状态改变的DOM已更新
      比如下面的例子, 在mounted中获取数据, 并更新dataList, 立即实例化Swiper, 此时
      dataList关联的DOM还没有更新完,所以Swiper实例化过早, $nextTick方法能确保DOM已更新,
      所以在该方法中实例化Swiper, 时机刚好
    */
    .swiper-container {
      width: 720px;
      height: 200px;
    }
  </style>
</head>

<body>
  <div id="app">
    <div class="swiper-container">
      <div class="swiper-wrapper">
        <div class="swiper-slide" v-for="data in dataList"><img :src="data"></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>

  <script>
    var vm = new Vue({
      el: "#app",
      data: {
        dataList: []
      },
      mounted() {
        setTimeout(() => {
          this.dataList = [
            "images/banner/1.jpg",
            "images/banner/2.jpg",
            "images/banner/3.jpg"
          ];
          this.$nextTick(() => {
            new Swiper(".swiper-container", {
              loop: true,
              pagination: {
                el: ".swiper-pagination"
              },
              // 如果需要前进后退按钮
              navigation: {
                nextEl: '.swiper-button-next',
                prevEl: '.swiper-button-prev',
              },

              // 自动播放
              autoplay: {
                delay: 2500,//延期时间
                disableOnInteraction: false,
              },

              // 如果需要滚动条
              scrollbar: {
                el: '.swiper-scrollbar',
              },
            })
          })

        }, 2000)
      }
    })

  </script>
</body>

3.swiper轮播实例化封装到指令

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>指令轮播</title>
  <script src="./js/vue.dev.js"></script>
  <script src="./js/swiper.min.js"></script>
  <link type="text/css" rel="styleSheet" href="./css/swiper.min.css">
  <style>
    .swiper-container {
      width: 720px;
      height: 200px;
    }

    /*
      指令轮播
      从mounted中的$nextTick中提取出实例化Swiper的代码, 创建指令swiper, 在指令inserted中, 判断
      当值的索引为最后一个时, 说明dom已经都插入完了, 此时实例化swiper

      需要注意的是:在调用指令时 v-swiper="{index:index,length:dataList.length}" , 传了一个对象参数
      在指令方法中, 通过bind.value得到这个对象参数 
    */
  </style>
</head>

<body>
  <div id="app">
    <div class="swiper-container">
      <div class="swiper-wrapper">
        <div class="swiper-slide" v-for="(data,index) in dataList" v-swiper="{index:index,length:dataList.length}"><img
            :src="data"> </div>
      </div>
      <div class="swiper-pagination"></div>
    </div>
  </div>
  <script>
    Vue.directive("swiper", {
      inserted(el, bind) {
        if (bind.value.index === bind.value.length - 1) {
          var swiper = new Swiper(".swiper-container", {
            loop: true,
            autoplay: {
              delay: 1500,
              disableOnInteraction: false,
            },
            pagination: {
              el: ".swiper-pagination"
            }
          })
        }
      }
    })

    var vm = new Vue({
      el: "#app",
      data: {
        dataList: []
      },
      mounted() {
        setTimeout(() => {
          this.dataList = [
            "./images/banner/1.jpg",
            "./images/banner/2.jpg",
            "./images/banner/3.jpg",
          ]
        }, 2000)
      }
    })

  </script>
</body>

16.过滤器

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>过滤器</title>
  <script src="./js/vue.dev.js"></script>
  <script src="./js/axios.js"></script>
  <style>
    ul li {
      list-style: none;
    }
  </style>
</head>

<body>
  <div id="app">
    <ul>
      <li v-for="data in movieList">
        <!-- <img :src="changeUrl(data.img)"> -->
        <img :src="data.img | changeUrl">
    </ul>
  </div>
</body>
<script>
  const apiUrl = "./data/movie.json"
  // 替换url, 使图片能加载成功
  Vue.filter("changeUrl", res => res.replace('w.h', '320.240'))
  var vm = new Vue({
    el: "#app",
    data: {
      movieList: []
    },
    methods: {
      initMovie() {
        axios.get(apiUrl).then(res => {
          this.movieList = res.data.movieList
        })
      },
      changeUrl(url) {
        return url.replace('w.h', '320.240')
      }
    },
    mounted() {
      this.initMovie()
    }


  })
</script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,458评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,030评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,879评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,278评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,296评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,019评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,633评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,541评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,068评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,181评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,318评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,991评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,670评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,183评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,302评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,655评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,327评论 2 358

推荐阅读更多精彩内容

  • ## 框架和库的区别?> 框架(framework):一套完整的软件设计架构和**解决方案**。> > 库(lib...
    Rui_bdad阅读 2,915评论 1 4
  • 1.基本绑定: new Vue( { el:'#elID', data:{ ...
    寒剑飘零阅读 532评论 0 1
  • 阻止同步 使用 Object.freeze(),这会阻止修改现有的属性,也意味着响应系统无法再追踪变化。 Vue实...
    Jack_1332阅读 296评论 0 0
  • vue实例 传进去的数值与外面的数值一直相等 在外面添加的属性不会随之改变 使用Object.freeze(obj...
    蛋黄肉阅读 409评论 0 0
  • 条件渲染: 1.v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值的时候被渲染。你可以使用...
    海的那一边阅读 251评论 0 1