vue学习记录

vue中常用的指令
 v-model
双向数据绑定,一般用于表单元素

 v-for
对数组或对象进行循环操作,使用的是v-for

<!-- 普通循环 -->
<li v-for="value in arr">{{value}}</li>

<!-- 键值循环 -->
<li v-for="(v,k) in arr">{{k}}={{v}}</li> 

<!-- 可以直接循环包含重复数据的集合,可以通过指定:key属性绑定唯一key,当更新元素时可重用元素,提高效率 ,变化的替换,不变的不替换

       官方解释:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在                           特定索引下显示已被渲染过的每个元素。

-->

<li v-for="(v,k) in arr2" :key="k">{{v}}</li> 

<li v-for="(user,index) in users">
{{index+1}},{{user.id}},{{user.name}},{{user.age}}
</li>

v-on
用来绑定事件,用法:v-on:事件="函数"        v-on:click="" 简写方式 @click=""         vue方法里的this表示当前vue实例  vue方法访问vue方法或数据都要用this,不能直接访问

v-show/v-if
用来显示或隐藏元素,v-show是通过display实现,v-if是每次删除后再重新创建

指令能直接访问vue实例中的数据

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <script src="js/vue.js"></script>
    <link rel="stylesheet" href="">
</head>
<body>

    <div id="app">
        <button @click="flag=!flag">显示或隐藏</button>

        <div style="width: 100px;height: 100px;background: red;" v-if="flag"></div>
    </div>


    <script type="text/javascript">
        window.onload=function(){
            new Vue({
                el:"#app",
                data:{
                    flag:false
                }
            });
        }
    </script>

</body>
</html>

用户管理例子

 

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <link rel="stylesheet" href="">
    <script src="js/vue.js"></script>
    <link rel="stylesheet" href="bootstrap/bootstrap.min.css">
    <script src="bootstrap/jquery.min.js"></script>
    <script src="bootstrap/bootstrap.min.js"></script>
</head>
<body>
    <div class="container">
        <h2 class="text-center">添加用户</h2>
        <form class="form-horizontal">
            <div class="form-group">
                <label for="userName" class="control-label col-lg-2 col-md-offset-2">姓名:</label>
                <div class="col-md-6">
                    <input type="text" id="userName" class="form-control" v-model="user.name" placeholder="请输入姓名"></input>
                </div>
            </div>
            <div class="form-group">
                <label for="userAge" class="control-label col-lg-2 col-md-offset-2">年龄:</label>
                <div class="col-md-6">
                    <input type="text" id="userAge" class="form-control" v-model="user.age" placeholder="请输入年龄"></input>
                </div>
            </div>
            <div class="form-group">
                <label for="userEmail" class="control-label col-lg-2 col-md-offset-2">邮箱:</label>
                <div class="col-md-6">
                    <input type="text" id="userEmail" class="form-control" v-model="user.email" placeholder="请输入邮箱"></input>
                </div>
            </div>
             <div class="form-group text-center">
                <input type="button" value="添加" class="btn btn-primary" @click="addUser">
                <input type="reset" value="重置" class="btn btn-primary">
             </div>
        </form><!-- form-horizontal -->

        <hr>
        <table class="table table-bordered table-hover" >
            <caption class="h3 text-center text-info"> 用户列表</caption>
            <thead>
                <tr >
                    <th class="text-center">序号</th>
                    <th class="text-center">姓名</th>
                    <th class="text-center">年龄</th>
                    <th class="text-center">邮箱</th>
                    <th class="text-center">操作</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(user,index) in users" class="text-center">
                    <td >{{index+1}} </td>
                    <td >{{user.name}} </td>
                    <td >{{user.age}} </td>
                    <td >{{user.email}} </td>
                    <td > <button class="btn btn-danger btn-sm"  data-toggle="modal" data-target="#del" @click="nowIndex=index">删除</button> </td>
                </tr>
                <tr >
                    <td colspan="5" class="text-right"> <button class="btn btn-danger " data-toggle="modal" data-target="#del"  @click="nowIndex=-1">删除所有</button></td>
                </tr>
            </tbody>
        </table>
        <!-- 模态框,弹出框 -->
        <div class="modal fade" id="del">
             <div class="modal-dialog">
                 <div class="modal-content">
                     <div class="modal-header">
                       <button class="close" data-dismiss="modal"> 
                           <span>&times;</span>
                       </button>
                       <div class="modat-titile" v-show="nowIndex!==-1">确定要删除{{users[nowIndex]?users[nowIndex].name:''}}吗?</div>
                       <div class="modat-titile" v-show="nowIndex===-1">确定要删除所有用户吗?</div>
                     </div>
                     <div class="modal-body text-center">
                         <button class="btn btn-primary" data-dismiss="modal">取消</button>
                         <button class="btn btn-primary" data-dismiss="modal" @click="deletUser">确定</button>
                     </div>
                 </div>
             </div>
        </div>
    </div>
     



    <script type="text/javascript">
        new Vue({
            el:".container",
            data:{
                users:[
                  {name:'蜡笔小新',age:'5',email:'110@110.com'},
                  {name:'樱桃小丸子',age:'3',email:'120@120.com'}
                ],
                user:{},
                nowIndex:-1
            },
            methods:{
                addUser:function(){
                   this.users.push(this.user);
                   this.user={};
                },

                deletUser:function(){
                    if (this.nowIndex===-1) {
                        this.users=[];
                    }else{
                        this.users.splice(this.nowIndex,1);
                    }
                    
                }

            }
        }); 
    </script>
</body>
</html>

 

 

{{msg}} <!-- 两对大括号{{}}称为模板,用来进行数据的绑定显示在页面中 -->

 

//配置是否允许vue-devtools检查代码,方便调试,默认为true,生产环境中需要设置为false
Vue.config.devtools=false;

 //阻止vue启动时生成生产消息(提示消息)
Vue.config.productionTip=false;

 

事件对象$event 

包含事件相关信息,如事件源、事件类型、偏移量
target、type、offsetx

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件简写和事件对象$event</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <button @click="print($event)" >点我</button>
    </div>


    <script type="text/javascript">
        new Vue({
            el:"#app",
            methods:{
                print:function(e){
                   console.log(e.target.innerHTML); //点我
                }
            }

        });
    </script>
</body>
</html>

阻止事件冒泡:
a)原生js方式,依赖于事件对象 e.stopPropagation();

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡和默认行为</title>
    <script src="js/vue.js"></script>
</head>
<body>
     <div class="app">
          <div @click="show3()">
              <p @click="show2()">
                  <button @click="show1($event)">点我</button>
              </p>
          </div>
     </div>

     <script type="text/javascript">
         new Vue({
             el:".app",
             methods:{
                show1:function(e){
                      e.stopPropagation();
                  console.log("11111");
                },
                show2:function(){
                  console.log("22222");
                },
                show3:function(){
                  console.log("33333");
                },
             }
         });
     </script>

</body>
</html>

 


b)vue方式,不依赖于事件对象e.preventDefault();
@click.stop

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡和默认行为</title>
    <script src="js/vue.js"></script>
</head>
<body>
     <div class="app">
          <div @click="show3()">
              <p @click="show2()">
                  <button @click.stop="show1()">点我</button>
              </p>
          </div>
     </div>

     <script type="text/javascript">
         new Vue({
             el:".app",
             methods:{
                show1:function(){
                      
                  console.log("11111");
                },
                show2:function(){
                  console.log("22222");
                },
                show3:function(){
                  console.log("33333");
                },
             }
         });
     </script>

</body>
</html>

 

阻止默认行为:
a)原生js方式,依赖于事件对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡和默认行为</title>
    <script src="js/vue.js"></script>
</head>
<body>
     <div class="app">
         <a href="https://www.baidu.com" title="" @click="change($event)">默认跳转到百度</a>
     </div>

     <script type="text/javascript">
         new Vue({
             el:".app",
             methods:{
               change:function(e){
                  e.preventDefault();
               }
             }
         });
     </script>

</body>
</html>

 

vue方式  @click.prevent 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡和默认行为</title>
    <script src="js/vue.js"></script>
</head>
<body>
     <div class="app">
         <a href="https://www.baidu.com" title="" @click.prevent="change()">默认跳转到百度</a>
     </div>

     <script type="text/javascript">
         new Vue({
             el:".app",
             methods:{
               change:function(){
                 console.log('不跳转');
               }
             }
         });
     </script>

</body>
</html>

 

 

键盘事件<!-- 键盘事件:@keydown、@keypress、@keyup -->

原生js 按键的判断(回车)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>键盘事件</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        <input type="text" @keydown="show($event)">
    </div>

    <script type="text/javascript">
        new Vue({
            el:".app",
            methods:{
               show:function(e){
                  if(e.keyCode==13){
                      console.log('你按了回车键');
                  }
               }
            }
        });
    </script>
</body>
</html>

 

vue方式按键的判断(回车) 简化按键的判断

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>键盘事件</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        <input type="text" @keydown.13="show()">
    </div>

    <script type="text/javascript">
        new Vue({
            el:".app",
            methods:{
               show:function(){
                  
                      console.log('你按了回车键');
                  
               }
            }
        });
    </script>
</body>
</html>

 


回车:@keydown.13 或@keydown.enter
上:@keydown.38 或@keydown.up

默认没有@keydown.a/b/c...事件,可以自定义键盘事件,也称为自定义键码或自定义键位别名

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>键盘事件</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        <input type="text" @keydown.a="show()">
        <input type="text" @keydown.f1.prevent="show1()">
    </div>
    <script type="text/javascript">
       Vue.config.keyCodes={
            a:65,
            f1:112
        }

        new Vue({
            el:".app",
            methods:{
               show:function(){
                  
                      console.log('你按了a键');
                  
               },
               show1:function(){
                  
                      console.log('你按了f1键');
                  
               }
            }
        });
    </script>
</body>
</html>

事件修饰符
.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。

input的修饰符

v-model.lazy.number.trim

 

 

 

属性绑定和属性的简写
v-bind 用于属性绑定, v-bind:属性=""

 

属性的简写:
v-bind:src="" 简写为 :src=""

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

vue实例的属性和方法

 

### 1. 属性    

vm.$el     vm.$data     vm.$options     vm.$refs

### 2. 方法    

vm.$mount()     vm.$destroy()     vm.$nextTick(callback)

 vm.$set(object,key,value)     vm.$delete(object,key)     vm.$watch(data,callback[,options])

能在vue之外通过vue实例的属性vm.$data直接访问vue内的数据等属性

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue实例的属性和方法</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        
    </div>
    
    <script>
      var vm = new Vue({
            el:'.app',
            data:{
                msg:'彭彭'
            }
        });
        
        console.log(vm.$data.msg);
        console.log(vm.msg);

    </script>
    
</body>
</html>

  //vm.$el 获取vue实例关联的元素
  // console.log(vm.$el); //DOM对象
  // vm.$el.style.color='red';

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue实例的属性和方法</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        ddd
    </div>
    
    <script>
      var vm = new Vue({
            el:'.app',
            data:{
                msg:'彭彭'
            }
        });
        
        console.log(vm.$el);
        vm.$el.style.color='red';

    </script>
    
</body>
</html>

 //vm.$options //获取自定义属性
  // console.log(vm.$options.name);
  // console.log(vm.$options.age);
  // vm.$options.show();

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue实例的属性和方法</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        ddd
    </div>
    
    <script>
      var vm = new Vue({
            el:'.app',
            data:{
                msg:'彭彭'
            },
            name:'peng',
            age:18,
            show:function(){
                 console.log("show");
            }
      });
        
      console.log(vm.$options.name);
      console.log(vm.$options.age);
      console.log(vm.$options.show);
    </script>
    
</body>
</html>

//vm.$refs 获取所有添加ref属性的元素
  // console.log(vm.$refs);
  // console.log(vm.$refs.hello); //DOM对象
  // vm.$refs.hello.style.color='blue';

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue实例的属性和方法</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        <div ref="hello1">hello</div>
        <div ref="hello2"></div>
    </div>
    
    <script>
      var vm = new Vue({
            el:'.app',
            data:{
                msg:'彭彭'
            }
        
      });
     
     console.log(vm.$refs);  
     console.log(vm.$refs.hello1); 
     vm.$refs.hello1.style.color="red";
     
    </script>
    
</body>
</html>

2. 方法     vm.$mount()     vm.$destroy()     vm.$nextTick(callback)

    vm.$set(object,key,value)     vm.$delete(object,key)     vm.$watch(data,callback[,options])

/**
   * 方法
   */
  //vm.$mount()  手动挂载vue实例
  // vm.$mount('#itany');

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue实例的方法</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        {{msg}}
    </div>
    
    <script>
      var vm = new Vue({
            
            data:{
                msg:'彭彭'
            }
        
      });
     
     vm.$mount('.app');
     
    </script>
    
</body>
</html> 

//vm.$destroy() 销毁实例  数据还在
  // vm.$destroy();

 

// vm.$nextTick(callback) 在DOM更新完成后再执行回调函数,一般在修改数据之后使用该方法,以便获取更新后的DOM

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue实例的方法</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        <h1 ref="title">标题{{msg}}</h1>
        
    </div>
    
    <script>
      var vm = new Vue({
            el:'.app',
            data:{
                msg:'彭彭'
            }
        
      });
     vm.msg='语文';
     //DOM还没更新完,Vue实现响应式并不是数据发生改变之后DOM立即变化,需要按一定的策略进行DOM更新,需要时间!!
     console.log(vm.$refs.title.textContent);

     vm.$nextTick(function(){
         //DOM更新完成,更新完成后再执行此代码
         console.log(vm.$refs.title.textContent);
     });
     
    </script>
    
</body>
</html>

 vm.$set(object,key,value) 增加属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加和删除属性:$set、$delete</title>
    <script src="js/vue.js"></script>
</head>
<body>
      <div class="app">
           <button @click="upData()">更新name</button>
           <button @click="addData()">增加属性</button>
          <h2>{{user.name}}</h2>    
          <h1>{{user.age}}</h1>       
      </div>

    <script>
      var vm = new Vue({
          el:'.app',
          data:{
              user:{
                id:1110,
                  name:'peng',
              }
          },
          methods:{
            upData:function(){
                this.user.name="cai";
            },
            addData:function(){
                //通过普通方式为对象添加属性时vue无法实时监视到
                // this.user.age=18;
                // console.log(this.user.age);

                //通过vue实例的$set方法为对象添加属性,可以实时监视,显示在{{}}里
                // this.$set(this.user,'age',18);
                // console.log(this.user.age);

                if(this.user.age){
                        this.user.age++;
                    }else{
                        //全局
                        Vue.set(this.user,'age',1);
                }
            }
          }
      });

    </script>
    
</body>
</html>

vm.$delete(object,key)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加和删除属性:$set、$delete</title>
    <script src="js/vue.js"></script>
</head>
<body>
      <div class="app">
           <button @click="delData()">删除属性</button>
          <h2>{{user.name}}</h2>    
          <h1>{{user.age}}</h1>       
      </div>

    <script>
      var vm = new Vue({
          el:'.app',
          data:{
              user:{
                id:1110,
                  name:'peng',
                  age:18
              }
          },
          methods:{
            delData:function(){
                if(this.user.age){
                    vm.$delete(this.user,'age');
                }
                  
            }
          }
      });

    </script>
    
</body>
</html>


监视数据的变化使用vm.$watch(data,callback[,options])

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>监视数据的变化:$watch</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        <input type="text" v-model="msg">

        <h1>{{msg}}</h1>

        <input type="text" v-model="msg2">

        <h1>{{msg2}}</h1>


        <input type="text" v-model="user.name">
        <h3>{{user.name}}</h3>
    </div>

    <script>
        vm = new Vue({
           el:".app",
           data:{
               msg:'',
               msg2:'msg2',
               user:{
                   name:'peng',
                   age:18
               }
           },
           watch:{
                 //方式2:使用vue实例提供的watch选项
              msg2:function(newValue,oldValue){
                  console.log("msg被修改了,原值:"+oldValue+" 新值:"+newValue);
              },
              //深度监视,当对象中的属性发生变化时也会监视
              user:{
                    handler:function(newValue,oldValue){
                        console.log("msg被修改了,原值:"+oldValue.name+" 新值:"+newValue.name);
                    },
                    deep:true
              }
           }
        });
       //方式1:使用vue实例提供的$watch()方法
        vm.$watch('msg',function(newValue,oldValue){
           console.log("msg被修改了,原值:"+oldValue+" 新值:"+newValue);
        });

    

    </script>
    
</body>
</html>

 

自定义指令     分类:全局指令、局部指令

### 1. 自定义全局指令     使用全局方法Vue.directive(指令ID,定义对象)

   

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义指令</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        <p  v-peng:wbs110.heh.hah="msg">{{msg}}</p>
        <button @click="change">更新数据</button>
    </div>

    <script>
        Vue.directive('peng',{
            bind:function(el,binding){
                console.log(el); //指令所绑定的元素,DOM对象
                el.style.color="red";
                console.log(binding);
                console.log('这是通过指令传经来的vue里的数据:'+binding.value);
                console.log('这是通过指令传经来的参数:'+binding.arg);
                console.log('这是通过指令传经来的修饰符:'+binding.modifiers.heh);
               alert('指令第一次绑定到元素上,且只执行一次,一般用于初始化!');
            },
            inserted:function(){
                alert('被绑定元素插入到DOM时执行');
            },
            update:function(){
                alert('被绑定元素所在的模板更新时执行');
            },
            componentUpdated:function(){
                alert('被绑定元素所在的模板完成一次更新周期时执行');
            },
            unbind(){
                alert('指令与元素解绑时调用,只调用一次');
            }
        });
        //传入一个简单的函数,bind和update时调用
        Vue.directive('wbs',function(){
            alert('wbs17022');
        });

        var vm=new Vue({
            el:".app",
            data:{
                msg:"彭彭"
            },
            methods:{
                change:function(){
                    this.msg="peng";
                }
            }
        });
    </script>
    
</body>
</html>

 

### 2. 自定义局部指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义指令</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div class="app">
        <input type="text" v-model="msg" v-focus>
        
    </div>

    <script>

        var vm=new Vue({
            el:".app",
            data:{
                msg:"彭彭"
            },
            methods:{
                change:function(){
                    this.msg="peng";
                }
            },
            directives:{ //自定义局部指令
                focus:{
                    //当被绑定元素插入到DOM中时获取焦点
                    inserted:function(el){
                        el.focus();
                    }
                }
            }
        });
    </script>
    
</body>
</html>

 

### 3. 练习     拖动页面中的元素     onmouseover onmouseout     onmousedown onmousemove  onmouseup

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定指令实现拖拽</title>
    <script src="js/vue.js"></script>
    <style type="text/css">
        .aa{
            
            width:100px;
            height: 100px;
            background: red;
            position:absolute;
        }
    </style>
</head>
<body>
    <div class="app">
        <div :class="{aa:true}" v-drag >
        
        </div>
    </div>

    <script>

        Vue.directive('drag',function(el){
             el.onmousedown=function(e){
                 var disX=e.clientX-el.offsetLeft;
                 var disY=e.clientY-el.offsetTop;
                 
                 document.onmousemove=function(e){
                     el.style.left=(e.clientX-disX)+'px';
                     el.style.top=(e.clientY-disY)+'px';
                 }
    
                 document.onmouseup=function(e){
                    document.onmousemove=null;
                    document.onmouseup=null;
                 }

             }
            
        });
        
        new Vue({
            el:".app",

        });
    </script>
    
</body>
</html>

过渡(动画)

### 1. 简介
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果
本质上还是使用CSS3动画:transition、animation

### 2. 基本用法
使用transition组件,将要执行动画的元素包含在该组件内
<transition>
运动的元素
</transition>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画</title>
    <script src="js/vue.js"></script>    
</head>
<style type="text/css">
    p{
        width: 300px;
        height: 300px;
        background: red;
    }
    .fade-enter-active,.fade-leave-active{
        transition: all 1s ease;        
    }

    .fade-enter-active{
        opacity: 1;
        width: 300px;
        height: 300px;
    }
    .fade-leave-active{
        opacity: 1;
        width: 100px;
        height: 100px;
    }
    .fade-enter{
        opacity: 0;
        height: 50px;
        width: 50px;
    }
</style>
<body>
     
     <div class="app">
         
         <button @click="flag=!flag">切换</button>
         
         <transition name="fade"
          @before-enter="beforeEnter"
            @enter="enter"
            @after-enter="afterEnter"
            @before-leave="beforeLeave"
            @leave="leave"
            @after-leave="afterLeave"
         > 
            <p  v-show="flag"></p>
        </transition>

     </div>

    <script>
        new Vue({
            el:".app",
            data:{
                flag:false     
            },
            methods:{
                beforeEnter(el){
                    alert('动画进入之前');
                },
                enter(){
                    // alert('动画进入');
                },
                afterEnter(el){
                    // alert('动画进入之后');
                    el.style.background='blue';
                },
                beforeLeave(){
                    // alert('动画即将之前');
                },
                leave(){
                    // alert('动画离开');
                },
                afterLeave(el){
                    // alert('动画离开之后');
                    el.style.background='red';
                }
            }   
        });
    </script>
    
</body>
</html>

 


过滤的CSS类名:6个

### 3. 钩子函数
8个

### 4. 结合第三方动画库animate..css一起使用
<transition enter-active-class="animated fadeInLeft" leave-active-class="animated fadeOutRight">
<p v-show="flag">网博</p>
</transition>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画</title>
    <link rel="stylesheet" href="css/animate.css">
    <script src="js/vue.js"></script>
    <style>
      p{
          width: 100px;
          height: 100px;
          background: red;
          margin: 20px auto;
      }
        
    </style>
</head>
<body>
      
      <div class="app">
           <button @click="flag=!flag">切换</button>
           
           <transition enter-active-class='animated hinge' leave-active-class='animated fadeOutRight'>
               <p v-show="flag"></p>
           </transition>
      </div>
      

    <script>
        new Vue({
            el:".app",
            data:{
                flag:false
            }
        });
    </script>
    
</body>
</html>

 

 

### 5. 多元素动画
<transition-group>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画</title>
    <link rel="stylesheet" href="css/animate.css">
    <script src="js/vue.js"></script>
    <style>
      p{
          width: 100px;
          height: 100px;
          background: red;
          margin: 20px auto;
      }
        
    </style>
</head>
<body>
      
      <div class="app">
           <button @click="flag=!flag">切换</button>
           
           <transition-group enter-active-class='animated hinge' leave-active-class='animated fadeOutRight'>
               <p v-show="flag" :key="1"></p>
               <p v-show="flag" :key="2"></p>
           </transition-group>
      </div>
      

    <script>
        new Vue({
            el:".app",
            data:{
                flag:false
            }
        });
    </script>
    
</body>
</html>

 

 

 

### 6. 练习
多元素动画

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>练习:多元素动画</title>
    <link rel="stylesheet" href="css/animate.css">
    <script src="js/vue.js"></script>
    <style>
        p{
            width: 100px;
            height: 100px;
            background-color:red;
            margin:20px auto;
        }
    </style>
</head>
<body>
    <div id="itany">
        <input type="text" v-model="name">
        
        <transition-group enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight">
            <p v-for="(v,k) in arr2" :key="k">
                {{v}}
            </p>
        </transition-group>
    </div>

    <script>
        var vm=new Vue({
            el:'#itany',
            data:{
                flag:true,
                arr:['tom','jack','mike','alice','alex','mark'],
                name:''
            },
            computed:{
                arr2:function(){
                    var temp=[];
                    this.arr.forEach(val => {
                        if(val.includes(this.name)){
                            temp.push(val);
                        }
                    });
                    return temp;
                }
            }
        });
    </script>
    
</body>
</html>

 


## 一、 组件component

### 1. 什么是组件?
组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码
组件是自定义元素(对象)

### 2. 定义组件的方式
方式1:先创建组件构造器,然后由组件构造器创建组件
方式2:直接创建组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>定义组件的两种方式</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="itany">
        <hello></hello>
        <my-world></my-world>
    </div>

    <script>
        /**
         * 方式1:先创建组件构造器,然后由组件构造器创建组件
         */
        //1.使用Vue.extend()创建一个组件构造器
        var MyComponent=Vue.extend({
            template:'<h3>Hello World</h3>'
        });
        //2.使用Vue.component(标签名,组件构造器),根据组件构造器来创建组件
        Vue.component('hello',MyComponent);
        
        /**
         * 方式2:直接创建组件(推荐)
         */
        // Vue.component('world',{
        Vue.component('my-world',{
            template:'<h1>你好,世界</h1>'
        });

        var vm=new Vue({ //这里的vm也是一个组件,称为根组件Root
            el:'#itany',
            data:{
                msg:'网博'
            }
        });    
    </script>
</body>
</html>

 

### 3. 组件的分类
分类:全局组件、局部组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件的分类</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="itany">
        <my-hello></my-hello>
        <my-world></my-world>
    </div>

    <script>
        /**
         * 全局组件,可以在所有vue实例中使用
         */
        Vue.component('my-hello',{
            template:'<h3>{{name}}</h3>',
            data:function(){ //在组件中存储数据时,必须以函数形式,函数返回一个对象
                return {
                    name:'alice'
                }
            }
        });

        /**
         * 局部组件,只能在当前vue实例中使用
         */
        var vm=new Vue({
            el:'#itany',
            data:{
                name:'tom'
            },
            components:{ //局部组件
                'my-world':{
                    template:'<h3>{{age}}</h3>',
                    data(){
                        return {
                            age:25
                        }
                    }
                }
            }
        });    
    </script>
</body>
</html>

 

### 4. 引用模板
将组件内容放到模板<template>中并引用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>引用模板</title>
    <script src="js/vue.js"></script>
</head>
<body>
    
    <div class="app">
        <my-comp></my-comp>
        <my-comp></my-comp>
    </div>
    <template id="tem">
        <div>
            <h3>{{msg}}</h3>
            <ul>
                <li v-for="value in arr">{{value}}</li>
            </ul>
        </div>        
    </template>

    <script>
        new Vue({
            el:".app",
            components:{
                'my-comp':{
                    template:'#tem',
                    name:'wbs17022',  //指定组件的名称,默认为标签名,可以不设置
                    data:function(){
                        return {
                            msg:'我的组件',
                            arr:['aa','bb','cc']
                        }
                    }
                }
            }
        });
    </script>
</body>
</html>

 

### 5. 动态组件
<component :is="">组件
多个组件使用同一个挂载点,然后动态的在它们之间切换

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动态组件</title>
    <script src="js/vue.js"></script>
</head>
<body>
      <div class="app">
           <button @click="flag='my-comp1'">组件1显示</button>
           <button @click="flag='my-comp2'">组件2显示</button>

           <div>
               <component :is="flag"></component>
           </div>
      </div>

    <script>
        new Vue({
            el:'.app',
            data:{
                flag:'my-comp1'
            },
            components:{
                "my-comp1":{
                    template:"<h3>组件1</h3>"
                },
                "my-comp2":{
                    template:"<h1>组件2</h1>"
                }


            }
        });
        
    </script>
</body>
</html>

 


<keep-alive>组件 <!-- 使用keep-alive组件缓存非活动组件,可以保留状态,避免重新渲染,默认每次都会销毁非活动组件并重新创建 -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动态组件</title>
    <script src="js/vue.js"></script>
</head>
<body>
      <div class="app">
           <button @click="flag='my-comp1'">组件1显示</button>
           <button @click="flag='my-comp2'">组件2显示</button>

           <div>
               <keep-alive>
                  <component :is="flag"></component>
              </keep-alive>
           </div>
      </div>

    <script>
        new Vue({
            el:'.app',
            data:{
                flag:'my-comp1'
            },
            components:{
                "my-comp1":{
                    template:"<h3>组件1 {{x}}</h3>",
                    data:function(){
                        return {
                            x:Math.random()
                        }
                    }
                },
                "my-comp2":{
                    template:"<h1>组件2 {{y}}</h1>",
                    data:function(){
                        return {
                            y:Math.random()
                        }
                    }
                }


            }
        });
        
    </script>
</body>
</html>

 

 

组件间数据传递

### 1. 父子组件
在一个组件内部定义另一个组件,称为父子组件
子组件只能在父组件内部使用
默认情况下,子组件无法访问父组件中的数据,父组件也无法访问子组件的数据,每个组件实例的作用域是独立的

### 2. 组件间数据传递 (通信)

#### 2.1 子组件访问父组件的数据
a)在调用子组件时,绑定想要获取的父组件中的数据
b)在子组件内部,使用props选项声明获取的数据,即接收来自父组件的数据
总结:父组件通过props向下传递数据给子组件
注:组件中的数据共有三种形式:data、props、computed

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父子组件及组件间数据传递</title>
    <script src="js/vue.js"></script>
</head>
<body>
    
    <div class="app">
        <far-comp></far-comp>
    </div>    
    
    <template id="far">
        <div>
            <h3>我是父组件,访问自己的数据:{{farmsg}}</h3>
            <son-comp :message="farmsg"></son-comp>
        </div>
    </template>
    <template id="son">
        <div>
            <h3>我是子组件,访问自己的数据:{{sonmsg}}</h3>
            <h3>我是子组件,访问父组件的数据:{{message}}</h3>
        </div>
    </template>
    <script>
        new Vue({
            el:'.app',
            components:{
                "far-comp":{
                    template:"#far",
                    data:function(){
                        return {
                            farmsg:'数据farmsg'
                        }
                    },
                    components:{
                        "son-comp":{
                            template:"#son",
                            props:{
                               message:String
                            },
                            data:function(){
                                return{
                                    sonmsg:'数据sonmsg'
                                }
                            }
                        }
                    }
                }
            }
        });
    </script>
</body>
</html>

 

#### 2.2 父组件访问子组件的数据
a)在子组件中使用vm.$emit(事件名,数据)触发一个自定义事件,事件名自定义
b)父组件在使用子组件的地方监听子组件触发的事件,并在父组件中定义方法,用来获取数据
总结:子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父子组件及组件间数据传递</title>
    <script src="js/vue.js"></script>
</head>
<body>
    
    <div class="app">
        <far-comp></far-comp>
    </div>    
    
    <template id="far">
        <div>
            <h3>我是父组件,访问自己的数据:{{farmsg}}</h3>
            <h3>我是父组件,访问子组件的数据:{{sonmsg}}</h3>
            <son-comp  @my-emit="getData" ></son-comp>
        </div>
    </template>
    <template id="son">
        <div>
            <h3>我是子组件,访问自己的数据:{{sonmsg}}</h3>
            <button @click="send()">触发自定义事件发送子组件数据</button>
        </div>
    </template>
    <script>
        new Vue({
            el:'.app',
            components:{
                "far-comp":{
                    template:"#far",
                    data:function(){
                        return {
                            farmsg:'数据farmsg',
                            sonmsg:''
                        }
                    },
                    methods:{
                        getData:function(sonmsg){
                            console.log(sonmsg);
                             this.sonmsg=sonmsg;
                        }
                    },
                    components:{
                        "son-comp":{
                            template:"#son",
                            data:function(){
                                return{
                                    sonmsg:'数据sonmsg'
                                }
                            },
                            methods:{
                                send:function(){
                                    console.log(this.sonmsg); //此处的this表示当前子组件实例
                                    console.log("执行了send()函数");
                                    this.$emit('my-emit',this.sonmsg);//使用$emit()触发一个事件,发送数据
                                }
                            }
                        }
                    }
                }
            }
        });
    </script>
</body>
</html>

 

### 3. 单向数据流

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单向数据流</title>
    <script src="js/vue.js"></script>
</head>
<body>
    
    <div class="app">
        <h3>我是父组件,我的数据是{{msg}}</h3>
        <son-comp :msg="msg"></son-comp>
    </div>
    
    <template id="son">
        <div>
            <h1>我是子组件,我的数据是:{{sonmsg}}</h1>
            <h1>我是子组件,我接收父组件数据是:{{msg}}</h1>
        </div>
    </template>

    <script>
    var vm = new Vue({
            el:".app",
            data:{
                msg:'父数据msg'
            },
            components:{
                'son-comp':{
                    template:"#son",
                    props:{
                        msg:String
                    },
                    data:function(){
                        return {
                            sonmsg:"子数据sonmsg",
                        }
                    }
                }
            }
        });
    </script>
</body>
</html>

 

props是单向绑定的,当父组件的属性变化时,将传导给子组件,但是不会反过来
而且不允许子组件直接修改父组件中的数据,报错
解决方式:
方式1:如果子组件想把它作为局部数据来使用,可以将数据存入另一个变量中再操作,不影响父组件中的数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>子组件想把从父组件得到的数据作为局部数据来使用</title>
    <script src="js/vue.js"></script>
</head>
<body>
    
    <div class="app">
        <h3>我是父组件,我的数据是{{msg}}</h3>
        <son-comp :msg="msg"></son-comp>
    </div>
    
    <template id="son">
        <div>
            <h1>我是子组件,我的数据是:{{sonmsg}}</h1>
            <h1>我是子组件,我接收父组件数据是:{{msg}}</h1>
            <h1>我是子组件,我接收父组件数据存到自己的data里:{{sonFar}}</h1>
            <input type="text" v-model="sonFar">
        </div>
    </template>

    <script>
    var vm = new Vue({
            el:".app",
            data:{
                msg:'父数据msg'
            },
            components:{
                'son-comp':{
                    template:"#son",
                    props:{
                        msg:String
                    },
                    data:function(){
                        return {
                            sonmsg:"子数据sonmsg",
                            sonFar:this.msg
                        }
                    }
                }
            }
        });
    </script>
</body>
</html>

 


方式2:如果子组件想修改数据并且同步更新到父组件,两个方法:
a.使用.sync(1.0版本中支持,2.0版本中不支持,2.3版本又开始支持)
需要显式地触发一个更新事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>子组件想修改数据并且同步更新到父组件</title>
    <script src="js/vue.js"></script>
</head>
<body>
    
    <div class="app">
        <h3>我是父组件,我的数据是{{msg}}</h3>
        <son-comp :msg.sync="msg"></son-comp>
    </div>
    
    <template id="son">
        <div>
            <h1>我是子组件,我的数据是:{{sonmsg}}</h1>
            <h1>我是子组件,我接收父组件数据是:{{msg}}</h1>
            <button @click="change()">子组件修改接收到父组件数据</button>
        </div>
    </template>

    <script>
    var vm = new Vue({
            el:".app",
            data:{
                msg:'父数据msg'
            },
            components:{
                'son-comp':{
                    template:"#son",
                    props:{
                        msg:String
                    },
                    data:function(){
                        return {
                            sonmsg:"子数据sonmsg",
                        }
                    },
                    methods:{
                        change:function(){
                            this.$emit('update:msg','子组件修改接收到父组件数据msg');
                        }
                    }
                }
            }
        });
    </script>
</body>
</html>

 


b.可以将父组件中的数据包装成对象,然后在子组件中修改对象的属性(因为对象是引用类型,指向同一个内存空间),推荐

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>子组件想修改数据并且同步更新到父组件(推荐)</title>
    <script src="js/vue.js"></script>
</head>
<body>
    
    <div class="app">
        <h3>我是父组件,我的数据是{{user.msg}}</h3>
        <son-comp :user="user"></son-comp>
    </div>
    
    <template id="son">
        <div>
            <h1>我是子组件,我的数据是:{{sonmsg}}</h1>
            <h1>我是子组件,我接收父组件数据是:{{user.msg}}</h1>
            <button @click="change()">子组件修改接收到父组件数据</button>
        </div>
    </template>

    <script>
    var vm = new Vue({
            el:".app",
            data:{
                user:{
                  msg:'父数据msg'
                }                
            },
            components:{
                'son-comp':{
                    template:"#son",
                    props:['user'],
                    data:function(){
                        return {
                            sonmsg:"子数据sonmsg",
                        }
                    },
                    methods:{
                        change:function(){
                            this.user.msg="子组件修改接收到父组件数据";
                        }
                    }
                }
            }
        });
    </script>
</body>
</html>

 

 

 

### 4. 非父子组件间的通信
非父子组件间的通信,可以通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件

var Event=new Vue();
Event.$emit(事件名,数据);
Event.$on(事件名,data => {});

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>非父子组件间的通信(数据比较简单时使用)</title>
    <script src="js/vue.js"></script>
</head>
<body>
     <div class="app">
        <a-comp></a-comp>
        <b-comp></b-comp>    
     </div>
     
     <template id="a">
         <div>
             <h3>我是a组件,我的数据是:{{msg}}</h3>
            <button @click="change()">把自己的数据msg发出去</button>
         </div>
     </template>
     <template id="b">
         <h1>我是b组件,我接收的数据是:{{msg}}</h1>
     </template>
    <script>
        var bush=new Vue();
        new Vue({
            el:".app",
            components:{
                'a-comp':{
                    template:"#a",
                    data:function(){
                        return {
                            msg:"a组件的msg"
                        }
                    },
                    methods:{
                        change:function(){
                           bush.$emit('e-send',this.msg);
                        }
                    }
                },
                'b-comp':{
                    template:"#b",
                    data:function(){
                        return {
                         msg:''    
                        }
                    },
                    mounted:function(){
                        //这里不能用function(msg){因为这里面的this指向调用它bush,而不是指向b-comp。所以要用msg=>,不改变this。还要注意:监听一定要在触发e-send事件之前,否则会监听不到e-send事件带来的数据}
                        bush.$on('e-send',msg=>{
                            this.msg=msg;
                        });
                    }
                }
            }
        });
    </script>
</body>
</html>

 

slot内容分发
本意:位置、槽
作用:用来获取组件中的原内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>slot内容分发</title>
    <script src="js/vue.js"></script>
</head>
<body>

    <div class="app">
        <my-comp>我是组件里填的内容</my-comp>
    </div>
     <template id="my">
         <div>
             <h3>我是组件</h3>
             <slot></slot>
         </div>
     </template>
    <script>
      new Vue({
          el:".app",
          components:{
              "my-comp":{
                  template:'#my',

              }
          }
      });
        
    </script>
</body>
</html>

组件里的内容会替换slot里的内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>slot内容分发</title>
    <script src="js/vue.js"></script>
</head>
<body>

    <div class="app">
        <my-comp>我是组件里填的内容</my-comp>
    </div>
     <template id="my">
         <div>
             <h3>我是组件</h3>
             <slot>我是slot里的内容</slot>
         </div>
     </template>
    <script>
      new Vue({
          el:".app",
          components:{
              "my-comp":{
                  template:'#my',

              }
          }
      });
        
    </script>
</body>
</html>

具名solt:决定组件里的内容是否显示以及显示的位置

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>slot内容分发</title>
    <script src="js/vue.js"></script>
</head>
<body>

    <div class="app">
        <my-comp>
            <div slot="content1">
                我是内容一
            </div>
            <div>
                我是内容二
            </div>
        </my-comp>
    </div>
     <template id="my">
         <div>
             <h3>我是组件</h3>
             <slot name="content1"></slot>
         </div>
     </template>
    <script>
      new Vue({
          el:".app",
          components:{
              "my-comp":{
                  template:'#my',

              }
          }
      });
        
    </script>
</body>
</html>

 

vue-router路由

### 1. 简介
使用Vue.js开发SPA(Single Page Application)单页面应用
根据不同url地址,显示不同的内容,但显示在同一个页面中,称为单页面应用

[参考](https://router.vuejs.org/zh-cn)

bower info vue-router
cnpm install vue-router -S

### 2. 基本用法
a.布局
b.配置路由

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>路由基本用法</title>
    <script src="js/vue.js"></script>
    <script src="js/vue-router.js"></script>
</head>
<body>
     <div class="app">
         <div>
             <router-link to="/us">我们</router-link>
             <router-link to="/news">新闻</router-link>
         </div>
         <div>
             <router-view></router-view>
         </div>
     </div>

    <script>
        var Us={
            template:"<h1>联系我们</h1>"
        };
        var News={
            template:"<h3>新闻内容</h3>"
        };

        const routes=[
           {path:'/us',component:Us},
           {path:'/news',component:News}
        ];
        const router = new VueRouter({
            routes:routes
        });

        new Vue({
            el:".app",
            router:router
        });
        
        
    </script>
</body>
</html>

模式、激活class、重定向

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>路由基本用法</title>
    <script src="js/vue.js"></script>
    <script src="js/vue-router.js"></script>
    <style type="text/css">
        .router-link-active{
            text-decoration: none;
            font-size: 36px;
            color: red;
        }
    </style>
</head>
<body>
     <div class="app">
         <div>
             <router-link to="/us">我们</router-link>
             <router-link to="/news">新闻</router-link>
         </div>
         <div>
             <router-view></router-view>
         </div>
     </div>

    <script>
        var Us={
            template:"<h1>联系我们</h1>"
        };
        var News={
            template:"<h3>新闻内容</h3>"
        };

        const routes=[
           {path:'*',redirect:'/us'},
           {path:'/us',component:Us},
           {path:'/news',component:News}
        ];
        const router = new VueRouter({
            routes:routes,
            // mode:"history",
            // linkActiveClass:'active' //更新活动链接的class类名
            
        });

        new Vue({
            el:".app",
            router:router
        });
        
        
    </script>
</body>
</html>

 

### 3. 路由嵌套和参数传递

路由嵌套

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>路由嵌套</title>
    <script src="js/vue.js"></script>
    <script src="js/vue-router.js"></script>
    <style type="text/css">
    .router-link-active{
        font-size:20px;
        color:#ff7300;
        text-decoration:none;
    }
    </style>
</head>
<body>
<div class="app">
    <div>
        <router-link to="/home">主页</router-link>
        <router-link to="/user">用户</router-link>
    </div>    
    <div>
        <router-view></router-view>
    </div>
    
</div>    
  

 <template id="user">
     <div>
         <h3>用户信息</h3>
         <ul>
             <router-link to="/user/login" tag="li">注册</router-link>
            <router-link to="/user/regist" tag="li">登陆</router-link>
         </ul>        
         <router-view></router-view>         
     </div>
 </template>
<script type="text/javascript">

    var Home={
        template:"<h3> 主页内容</h3>"
    };
    var User={
        template:"#user"
        // template:"<h2>yon</h2>"
    };
    var Regist={
        template:"<h1>登陆页面。。。。</h1>"
    };
    var Login={
        template:"<h1>注册页面。。。</h1>"
    };
    const routes=[
      {
        path:"/Home",
        component:Home
      },
      {
          path:"/user",
          component:User,
        children:[
         {
             path:'regist',
             component:Regist
         },
         {
             path:'login',
             component:Login
         }
        ]
      }
      
    ];
    const router=new VueRouter({
        routes:routes
    });
    new Vue({
        el:".app",
        router:router
    });
</script>    
</body>
</html>

 


传参的两种形式:
a.查询字符串:login?name=tom&pwd=123
{{$route.query}}
b.rest风格url:regist/alice/456
{{$route.params}}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>路由传参数</title>
    <script src="js/vue.js"></script>
    <script src="js/vue-router.js"></script>
    <style type="text/css">
    .router-link-active{
        font-size:20px;
        color:#ff7300;
        text-decoration:none;
    }
    </style>
</head>
<body>
<div class="app">
    <div>
        <router-link to="/home">主页</router-link>
        <router-link to="/user">用户</router-link>
    </div>  
    <div>
        <router-view></router-view>
    </div>
    
</div>  
  

 <template id="user">
    <div>
        <h3>用户信息</h3>
        <ul>
            <router-link to="/user/login?name=peng&pwd=123" tag="li">注册</router-link>
            <router-link to="/user/regist/peng/123" tag="li">登陆</router-link>
        </ul>       
        <router-view></router-view>         
    </div>
 </template>
<script type="text/javascript">

    var Home={
        template:"<h3> 主页内容</h3>"
    };
    var User={
        template:"#user"
    };
    var Regist={
        template:"<h1>登陆页面。。。。获取的参数是:{{$route.params}}</h1>"
    };
    var Login={
        template:"<h1>注册页面。。。获取的参数是:{{$route.query}}</h1>"
    };
    const routes=[
      {
        path:"/Home",
        component:Home
      },
      {
        path:"/user",
        component:User,
        children:[
         {
            path:'regist/:name/:pwd',
            component:Regist
         },
         {
            path:'login',
            component:Login
         }
        ]
      }
      
    ];
    const router=new VueRouter({
        routes:routes
    });
    new Vue({
        el:".app",
        router:router
    });
</script>   
</body>
</html>

 


### 4. 路由实例的方法
router.push() 添加路由,功能上与<route-link>相同

router.replace() 替换路由,不产生历史记录

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>路由切换</title>
    <script src="js/vue.js"></script>
    <script src="js/vue-router.js"></script>
    <style type="text/css">
    .router-link-active{
        font-size:20px;
        color:#ff7300;
        text-decoration:none;
    }
    </style>
</head>
<body>
<div class="app">
    <div>
        <router-link to="/home">主页</router-link>
        <router-link to="/user">用户</router-link>
    </div>  
    <div>
        <router-view></router-view>
    </div>
    <button @click="change()">切换路由</button>
    <button @click="replace()">替换路由</button>
    
</div>  
  

 <template id="user">
    <div>
        <h3>用户信息</h3>
        <ul>
            <router-link to="/user/login" tag="li">注册</router-link>
            <router-link to="/user/regist" tag="li">登陆</router-link>
        </ul>       
        <router-view></router-view>         
    </div>
 </template>
<script type="text/javascript">

    var Home={
        template:"<h3> 主页内容</h3>"
    };
    var User={
        template:"#user"
        // template:"<h2>yon</h2>"
    };
    var Regist={
        template:"<h1>登陆页面。。。。</h1>"
    };
    var Login={
        template:"<h1>注册页面。。。</h1>"
    };
    const routes=[
      {
        path:"/home",
        component:Home
      },
      {
        path:"/user",
        component:User,
        children:[
         {
            path:'regist',
            component:Regist
         },
         {
            path:'login',
            component:Login
         }
        ]
      }
      
    ];
    const router=new VueRouter({
        routes:routes
    });
    new Vue({
        el:".app",
        router:router,
        methods:{
            change:function(){
                router.push({path:'home'});
            },
            replace:function(){
                router.replace({path:'user'});
            }
        }
    });
</script>   
</body>
</html>

 

 

### 5. 路由结合动画

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>路由结合动画</title>
    <link rel="stylesheet" href="css/animate.css">
    <script src="js/vue.js"></script>
    <script src="js/vue-router.js"></script>
    <style type="text/css">
    .router-link-active{
        font-size:20px;
        color:#ff7300;
        text-decoration:none;
    }
    </style>
</head>
<body>
<div class="app">
    <div>
        <router-link to="/home">主页</router-link>
        <router-link to="/user">用户</router-link>
    </div>  
    <div>
        <transition enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight">
        <transition enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight">
            <router-view></router-view>
        </transition>        
    </div>
    
</div>  
  

 <template id="user">
    <div>
        <h3>用户信息</h3>
        <ul>
            <router-link to="/user/login" tag="li">注册</router-link>
            <router-link to="/user/regist" tag="li">登陆</router-link>
        </ul>    
             <router-view></router-view>
    </div>
 </template>
<script type="text/javascript">

    var Home={
        template:"<h3> 主页内容</h3>"
    };
    var User={
        template:"#user"
        // template:"<h2>yon</h2>"
    };
    var Regist={
        template:"<h1>登陆页面。。。。</h1>"
    };
    var Login={
        template:"<h1>注册页面。。。</h1>"
    };
    const routes=[
      {
        path:"/Home",
        component:Home
      },
      {
        path:"/user",
        component:User,
        children:[
         {
            path:'regist',
            component:Regist
         },
         {
            path:'login',
            component:Login
         }
        ]
      }
      
    ];
    const router=new VueRouter({
        routes:routes
    });
    new Vue({
        el:".app",
        router:router
    });
</script>   
</body>
</html>

.vue文件
.vue文件,称为单文件组件,是Vue.js自定义的一种文件格式,一个.vue文件就是一个单独的组件,在文件内封装了组件相关的代码:html、css、js

.vue文件由三部分组成:<template>、<style>、<script>
<template>
html
</template>

<style>
css
</style>

<script>
js
</script>

### 2. vue-loader
浏览器本身并不认为.vue文件,所以必须对.vue文件进行加载解析,此时需要vue-loader
类似的loader还有许多,如:html-loader、css-loader、style-loader、babel-loader等
需要注意的是vue-loader是基于webpack的

### 3. webpack
webpack是一个前端资源模板化加载器和打包工具,它能够把各种资源都作为模块来使用和处理
实际上,webpack是通过不同的loader将这些资源加载后打包,然后输出打包后文件
简单来说,webpack就是一个模块加载器,所有资源都可以作为模块来加载,最后打包输出

[官网](http://webpack.github.io/)

webpack版本:v1.x v2.x

webpack有一个核心配置文件:webpack.config.js,必须放在项目根目录下

 

示例,步骤:

#### 4.1 创建项目,目录结构 如下:
webpack-demo
|-index.html
|-main.js 入口文件
|-App.vue vue文件
|-package.json 工程文件
|-webpack.config.js webpack配置文件
|-.babelrc Babel配置文件

### 4.2 编写App.vue

### 4.3 安装相关模板
cnpm install vue -S

cnpm install webpack -D  //生产依赖
cnpm install webpack-dev-server -D  // 访问webpack,搭建服务器

cnpm install vue-loader -D  
cnpm install vue-html-loader -D 
cnpm install css-loader -D
cnpm install vue-style-loader -D
cnpm install file-loader -D  //用到字体字库

cnpm install babel-loader -D   //ES6语法
cnpm install babel-core -D    //核心
cnpm install babel-preset-env -D //根据配置的运行环境自动启用需要的babel插件
cnpm install vue-template-compiler -D //预编译模板

合并:cnpm install -D webpack webpack-dev-server vue-loader vue-html-loader css-loader vue-style-loader file-loader babel-loader babel-core babel-preset-env vue-template-compiler

### 4.4 编写main.js

/**
 * 使用ES6语法引入模板
 */
import Vue from 'vue'  //会去node_modules去找(vue装在这里),
import App from './App.vue' //虽然在同一目录,但因为它不是内部模块,而是自定义模块,所以要加 ./

new Vue({
    el:'#app', //App.vue里要应用
    render:function(h){ //使用render函数渲染组件 :组件注册等价与components
        return h(App);
    }
});

 

 

### 4.5 编写webpack.config.js

module.exports={
    //配置入口文件
    entry:'./main.js',
    //配置入口文件输出位置
    output:{
        path:__dirname, //项目根路径
        filename:'build.js'
    },
    //配置模块加载器
    module:{
        rules:[
            {
                test:/\.vue$/, //所有以.vue结尾的文件都由vue-loader加载
                loader:'vue-loader'
            },
            {
                test:/\.js$/, //所有以.js结尾的文件都由babel-loader加载,除了node_modules以外
                loader:'babel-loader',
                exclude:/node_modules/
            }
        ]
    }
}

 

### 4.6 编写.babelrc

{
    "presets":[
        ["env",{"module":false}]
    ]
}

 

### 4.7 编写package.json

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "dev":"webpack-dev-server --open --hot --port 8800"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "vue": "^2.3.4"
  },
  "devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.1",
    "babel-preset-env": "^1.5.2",
    "css-loader": "^0.28.4",
    "file-loader": "^0.11.2",
    "vue-html-loader": "^1.2.4",
    "vue-loader": "^13.0.0",
    "vue-style-loader": "^3.0.1",
    "vue-template-compiler": "^2.3.4",
    "webpack": "^3.0.0",
    "webpack-dev-server": "^2.5.0"
  }
}

 

### 4.8 运行测试
npm run dev

 

 

vue-cli脚手架

### 1. 简介
vue-cli是一个vue脚手架,可以快速构造项目结构
vue-cli本身集成了多种项目模板:
simple 很少简单
webpack 包含ESLint代码规范检查和unit单元测试等
webpack-simple 没有代码规范检查和单元测试
browserify 使用的也比较多
browserify-simple

### 2. 示例,步骤:

#### 2.1 安装vue-cli,配置vue命令环境
cnpm install vue-cli -g
vue --version
vue list

#### 2.2 初始化项目,生成项目模板
语法:vue init 模板名 项目名

#### 2.3 进入生成的项目目录,安装模块包
cd vue-cli-demo
cnpm install

#### 2.4 运行
npm run dev //启动测试服务
npm run build //将项目打包输出dist目录,项目上线的话要将dist目录拷贝到服务器上

### 3. 使用webpack模板
vue init webpack vue-cli-demo2

ESLint是用来统一代码规范和风格的工具,如缩进、空格、符号等,要求比较严格
[官网](http://eslint.org)

问题Bug:如果版本升级到node 8.0 和 npm 5.0,控制台会报错:
GET http://localhost:8080/__webpack_hmr net::ERR_INCOMPLETE_CHUNKED_ENCODING
解决方法:
a)降低Node版本到7.9或以下
b)修改build/dev-server.js文件,如下:
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {},
heartbeat:2000 //添加此行
})
参考:https://github.com/vuejs-templates/webpack/issues/731

 

 

 

一个项目从开始

2.1 安装vue-cli,配置vue命令环境
cnpm install vue-cli -g
vue --version
vue list

#### 2.2 初始化项目,生成项目模板
语法:vue init 模板名(webpack-simple) 项目名

<? License (MIT) no
? License no
? Use sass? (y/N) N
? Use sass? No
>

#### 2.3 进入生成的项目目录,安装模块包
cd vue-cli-demo
cnpm install

#### 2.4 运行
npm run dev //启动测试服务
<用vue-router
cnpm install vue-router -S
>

npm run build //将项目打包输出dist目录,项目上线的话要将dist目录拷贝到服务器上

模块化开发

### 1. vue-router模块化
cnpm install vue-router -S

#### 1.1 编辑main.js

#### 1.2 编辑App.vue

<template>
  <div id="app">
     <div>
         <router-link to="/home">主页</router-link>
         <router-link to="/news">新闻</router-link>
     </div>
     <keep-alive>
        <router-view></router-view>
     </keep-alive>
  </div>
</template>

<script>
export default {
  name: 'app',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
   mounted:function(){
    console.log(this.$route)
  },
  watch:{
    $route:function(newValue,oldValue){
        console.log('路由发生了变化,跳转到:'+oldValue.path);
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

h1, h2 {
  font-weight: normal;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
  margin: 0 10px;
}

a {
  color: #42b983;
}
</style>

 

#### 1.3 编辑router.config.js

### 2. axios模块化
cnpm install axios -S

使用axios的两种方式:
方式1:在每个组件中引入axios

<template>
  <div id="app">
     <div>
         <router-link to="/home">主页</router-link>
         <router-link to="/news">新闻</router-link>
     </div>
     <keep-alive>
        <router-view></router-view>
     </keep-alive>


     <hr>
  <button @click="send">发送AJAX请求</button>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  name: 'app',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
   mounted:function(){
    console.log(this.$route)
  },
  watch:{
    $route:function(newValue,oldValue){
        console.log('路由发生了变化,跳转到:'+oldValue.path);
    }
  },
  methods:{
    send:function(){
       axios.get('https://api.github.com/users/tangyang8942')
       .then(function(resp){
          console.log(resp);
       }).catch(function(){
           console.log('请求失败');
       });
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

h1, h2 {
  font-weight: normal;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
  margin: 0 10px;
}

a {
  color: #42b983;
}
</style>

 


方式2:在main.js中全局引入axios并添加到Vue原型中

 

 

 

### 3. 为自定义组件添加事件

 

 <Mybutton @click.native="send"></Mybutton>

 

 

Elment UI

### 1. 简介
Element UI是饿了么团队提供的一套基于Vue2.0的组件库,可以快速搭建网站,提高开发效率
ElementUI PC端
MintUI 移动端

[官网](http://element.eleme.io/)

### 2. 快速上手

#### 2.1 安装elment ui
cnpm install element-ui -S

#### 2.2 在main.js中引入并使用组件
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css' //该样式文件需要单独引入
Vue.use(ElementUI);
这种方式引入了ElementUI中所有的组件

 

#### 2.3 在webpack.config.js中添加loader
CSS样式和字体图标都需要由相应的loader来加载,所以需要style-loader、css-loader

 

默认并没有style-loader模块,所以需要单独安装
cnpm install style-loader --save-dev

 

<template>
  <div id="app">

    <h1>{{ msg }}</h1>
    <hr>
    <el-button type="primary">我的按钮</el-button>
    <el-button round>圆角按钮</el-button>
  <el-button icon="el-icon-search" circle></el-button>
  <el-button type="primary" icon="el-icon-edit" circle></el-button>
  <el-button type="success" icon="el-icon-check" circle></el-button>
  <el-button type="info" icon="el-icon-message" circle></el-button>
  <el-button type="warning" icon="el-icon-star-off" circle></el-button>
  <el-button type="danger" icon="el-icon-delete" circle></el-button>
    
  </div>
</template>

<script>
export default {
  name: 'app',
  data () {
    return {
      msg: '彭彭'
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

h1, h2 {
  font-weight: normal;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
  margin: 0 10px;
}

a {
  color: #42b983;
}
</style>

 

#### 2.4 使用组件

#### 2.5 使用less
安装loader,需要两个:less、less-loader
cnpm install less less-loader -D
在webpack.config.js中添加loader

### 3. 按需引入组

#### 3.1 安装babel-plugin-component
cnpm install babel-plugin-component -D

#### 3.2 配置.babelrc文件
"plugins": [["component", [
{
"libraryName": "element-ui",
"styleLibraryName": "theme-default"
}
]]]

#### 3.3 只引入需要的插件


## 三、 自定义全局组件(插件)

全局组件(插件):就是指可以在main.js中使用Vue.use()进行全局引入,然后在其他组件中就都可以使用了,如vue-router
import VueRouter from 'vue-router'
Vue.use(VueRouter);

普通组件(插件):每次使用时都要引入,如axios
import axios from 'axios'

 

 

 

Vuex

### 1. 简介
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
简单来说,用来集中管理数据,类似于React中的Redux,都是基于Flux的前端状态管理框架

### 2. 基本用法

#### 2.1 安装vuex
cnpm install vuex -S

 

#### 2.2 创建store.js文件,在main.js中导入并配置store.选项

#### 2.3 编辑store.js文件
Vuex的核心是Store(仓库),相当于是一个容器,一个store实例中包含以下属性的方法:
state 定义属性(状态、数据)
getters 用来获取属性
actions 定义方法(动作)
commit 提交变化,修改数据的唯一方式就是显式的提交mutations
mutations 定义变化
注:不能直接修改数据,必须显式提交变化,目的是为了追踪到状态的变化

#### 2.4 编辑App.vue
在子组件中访问store对象的两种方式:
方式1:通过this.$store访问
方式2:通过mapState、mapGetters、mapActions访问,vuex提供了两个方法:
mapState 获取state
mapGetters 获取getters
mapActions 获取actions

 

### 3. 分模块组织Vuex

|-src
      |-store
             |-index.js
             |-getters.js
             |-actions.js
             |-mutations.js
             |-modules //分为多个模块,每个模块都可以拥有自己的state、getters、actions、mutations
                    |-user.js
                    |-cart.js
                    |-goods.js
                    |....

 

 

 

## 一、 准备工作

###1. 初始化项目
vue init webpack itany
cd itany
cnpm install
cnpm install less less-loader -D
cnpm install vuex axios -S
npm run dev

### 2. 项目资源
|-reset.css
|-data.json

### 3. 创建目录结构
首先清除项目中的部分内容

创建如下目录结构:
|-data.json
|-static
     |-css
          |-reset.css

### 4. 配置API接口,模拟后台数据
使用express框架启动一个Node服务器,配置API接口,模拟后台数据

测试API:
http://localhost:8080/api/seller
http://localhost:8080/api/goods
http://localhost:8080/api/ratings


## 二、项目整体结构开发

 

posted @ 2018-05-16 20:36  pengc  阅读(335)  评论(0编辑  收藏  举报