Vue-one 一:vue指令: 组件的切换: vue路由

<div id="app">
   //使用v-cloak,可以解决插值表达式的闪烁问题 ,不会覆盖元素中原有的内容,只会替换自己的占位符
   <p v-cloak>11111{{msg1}}9999</p>
   //没有闪烁问题,但是会覆盖原有的内容 
   <h1 v-text="msg2"></h1>
   //输出html格式,会覆盖元素中原有的内容 
   <h1 v-html="msg2"></h1>
   //v-bind 可以简写为:,绑定属性的指令
   <input type="button" value="按钮" v-bind:title="mytitle">
   <input type="button" value="按钮" :title="mytitle">
   //v-bind会把后面的当作js表达式执行,后面可以写合法的表达式,mytitle变量+表达式 
   <input type="button" value="按钮" :title="mytitle + '123'">
   //v-on:click 绑定事件,相当于onclick
   <input type="button" value="按钮" :title="mytitle + '123'" v-on:click="handle">
   //v-on:缩写为@
   <input type="button" value="按钮" :title="mytitle + '123'" @click="handle">
</div>

vue代码:

var vm = new Vue({
        el: '#app',
        // 数据
        data: {
            msg1: '哈哈哈哈',
            msg2: '<h1>kkkkkk</h1>',
            mytitle: 'title',
        },
        // 对象
        methods: {
            handle: function () {
                alert("hello");
            }
        }
    });

例子:跑马灯效果

substring 来进行字符串的截取,把第一个截取放最后面

html代码如下:

<div class="app2">
        <input type="button" value="开始" v-on:click="handle1">
        <input type="button" value="停止" v-on:click="handle2">
        <h4>{{ msg }}</h4>
</div>

vue代码如下:

var vm = new Vue({
        el: '.app2',
        data: {
            msg: '这是一个跑马灯效果',
            timer: null,
        },
        methods: {
            // 在vm实例中,要获取data的数据,或者是methods的方法,必须要this.属性名数据或this.方法名
            // handle1: function () {
            //     // console.log(this.msg);
            //     var _this=this;
            //     setInterval(function () {
            //         // 获取第一个字符
            //         var start = _this.msg.substring(0, 1);
            //         // 从第一个截取到最后
            //         var end = _this.msg.substring(1);
            //         // 从新拼接,赋值给msg
            //         _this.msg = end + start;
            //     },1000)
            // },
            // handle2: function () {
            // }
            // es6写法,可以省略function,箭头函数可以指向外面的this
            handle1() {
                if (this.timer != null) {
                    return;
                }
                this.timer = setInterval(() => {
                    // 获取第一个字符
                    var start = this.msg.substring(0, 1);
                    // 从第一个截取到最后
                    var end = this.msg.substring(1);
                    // 从新拼接,赋值给msg
                    this.msg = end + start;
                }, 1000)
            },
            handle2() {
                clearInterval(this.timer);
                this.timer = null;
            }
        },
    })
v-on事件修饰符:
//<!-- capture捕获事件,从外到里输出 -->
    <div id="app3" @click="divHandle">
        //<!-- .stop阻止冒泡 -->
        <input type="button" value="点1" @click.stop="btnHandle1">
        //<!-- self点击当前元素的时候才会触发当前事件 -->
        <input type="button" value="点2" @click.self="btnHandle2">
        //<!-- prevent阻止默认行为 -->
        <a href="http://www.baidu.com" @click.prevent="linkClick">app</a>
        //<!-- once只执行一次 -->
        <a href="http://www.baidu.com"     @click.prevent.once="linkClick">app</a>
 </div>
var vm = new Vue({
        el: '#app3',
        data: {},
        methods: {
            divHandle() {alert("这是div的点击事件");},
            btnHandle1() {alert("这是button的点击事件");},
            btnHandle2() {alert("self");},
            linkClick() {alert("Baidu");}
        }
    });

  v-model:数据绑定

//<!-- v-model双向数据绑定,只能运用于表单元素,radio,text,address,mail,select,CheckBox -->
<div id="app1">
   <h4>{{msg1}}</h4>
   <input type="text" v-model:value="msg1" style=" 500px;">
</div>
var vm = new Vue({
        el: '#app1',
        data: {
            msg1: 'hellodfdfddkfjdfjdfjdkfdkfjdkfjkdfjd',
        },
        methods: {}
    });

例子:使用v-model实现计算器案例

<div id="app2">
        <input type="text" name="" id="" v-model="msg1">
        <select v-model="opt">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>
        <input type="text" name="" id="" v-model="msg2">
        <input type="button" value="=">
        <input type="text" name="" id="" v-model="result">
        <input type="button" value="计算" @click="calc">
</div>
var vm = new Vue({
        el: '#app2',
        data: {
            msg1: '0',
            msg2: '0',
            result: '0',
            opt: '-'
        },
        methods: {
            calc() {
                // 方法一
                //     switch (this.opt){
                //         case '+':this.result =parseInt(this.msg1)+parseInt(this.msg2);break ;
                //         case '-':this.result =parseInt(this.msg1)-parseInt(this.msg2);break ;
                //         case '*':this.result =parseInt(this.msg1)*parseInt(this.msg2);break ;
                //         case '/':this.result =parseInt(this.msg1)/parseInt(this.msg2);break ;
                //     }
                // 方法二
                var codeStr = 'parseInt(this.msg1)' + this.opt + 'parseInt(this.msg2)';
                this.result = eval(codeStr);
            },
        }
    });

vue使用样式:

<div id="app3">
        <h2>第一种:数组</h2>
        <h1 :class="['wraper1','wraper2','wraper3']">hkdlfjhklddhfjdfkd</h1>
        <h2>第一种:在数组中使用三元表达式</h2>
        <h1 :class="['wraper1','wraper2',flag?'wraper3':'']">1211111111</h1>
        <h2>第一种:在数组写对象,提高可读性,flag为true就显示</h2>
        <h1 :class="['wraper1',{'wraper2':flag},'wraper3']">1211111111</h1>
        <h2>第一种:直接使用对象</h2>
        <!-- class 使用v-bind绑定对象的属性时,由于对象的属性是类名,所以,对象的属性可带引号,可不带,属性的值是标识符 -->
        <h1 :class="{wraper1:true,wraper2:false,wraper3:false}">1211111111</h1>
        <!-- 把他放在属性里面 -->
        <h1 :class="obj">1211111111</h1>
</div>
new Vue({
        el: '#app3',
        data: {
            flag: true,
            obj: { wraper1: true, wraper2: true, wraper3: false },
        }
    });
v-for指令:
<div id="app5">
        <p v-for="item in list1">{{item}}</p>
        <p v-for="(item,i) in list1">索引值{{i}}+" "+{{item}}</p>
        //<!-- 遍历数组 -->
        <p v-for="(item,i) in list2">{{item.id}}+" "+{{item.name}}+" "+索引值{{i}}</p>
        //<!-- 遍历对象 -->
        <p v-for="(value,key,i) in list3">值:{{value}}+" "+键:{{key}}+" "+索引值{{i}}</p>
       // <!-- 迭代数组, 如果使用数字时从1开始-->
        <p v-for="count in 10">这是第{{count}}次</p>
        <h1>v-for使用注意事项<h1>
        id:<input type="text" v-model="id">
        name:<input type="text" v-model="name">
        <input type="button" value="添加" @click="add">
        //<!--v-for key只能使用number或string,key使用时要用v-bind  -->
        //<!-- 在组件中使用v-for,或特殊情况,使用时有问题,必须指定唯一的 字符串、数字类型的key -->
        <p v-for="(item,i) in list2" v-bind:key="item.id">
        <input type="checkbox" name="" id="">{{item.id}}+" "+{{item.name}}</p>
</div>
new Vue({
        el: '#app5',
        data: {
            id: '',
            name: '',
            list1: [1, 2, 3, 4, 5],
            list2: [
                { id: 1, name: 'lisi1' },
                { id: 2, name: 'lisi2' },
                { id: 3, name: 'lisi3' },
                { id: 4, name: 'lisi4' }
            ],
            list3: {
                id: 1,
                name: 'haha',
                age: 12,
                adddress: '中国',
            }
        },
        methods: {
            add() {
                this.list2.push({ id: this.id, name: this.name })
            }
        }
    });

v-if:

<div id="app6">
        //<!-- <input type="button" value="toggle" @click="toggle"> -->
        //<!-- 等于下面的 -->
        <input type="button" value="toggle" @click="flag=!flag">
        <h3 v-if="flag">这是v-if控制的元素</h3>
        <h3 v-show="flag">这是v-show控制的元素</h3>
        //<!-- v-if每一次都会重新删除和创建元素 ,有较高的切换性能消耗
        如果元素频繁的切换,最好不要使用-->
        //<!-- v-show每一次都不会重新删除和创建元素 ,只是切换了元素的dispaly:none样式,有较高的初始渲染消耗
        如果元素可能永远也不会显示出来被用户看,推荐使用-->
</div>
new Vue({
        el: '#app6',
        data: {
            flag: true,
        },
        methods: {
            toggle() {
                this.flag = !this.flag;
            }
        }
    });

品牌例子:

<div id="day1">
        <div class="panel panel-primary">
            <div class="panel-heading">
                <h1 class="panel-title">添加品牌</h1>
            </div>
            <div class="panel-body form-inline">
                <label>
                    id:<input type="text" name="" id="" class="form-control" v-model="id">
                </label>
                <label>
                    //<!-- @keyup="add"是键盘抬起触发add事件 .enter键盘抬起按enter键就可以触发-->
                    name:<input type="text" name="" id="" class="form-control" v-model="name" @keyup.enter="add">
                </label>
                <label>
                    //<!-- v-color=('blue')是传递的值 -->
                    搜索关键字:<input type="text" name="" id="" class="form-control" v-model="keywords" v-focus
                        v-color=('blue')>
                </label>
                //<!-- 在vue中使用事件绑定,如果加了小括号就可以传参数add() -->
                <input type="button" value="添加" class="btn btn-primary" @click="add">
            </div>
        </div>
        <table class="table table-bordered table-hover table-striped">
            <thead>
                <tr>
                    <th>id</th>
                    <th>name</th>
                    <th>time</th>
                    <th>option</th>
                </tr>
            </thead>
            <tbody>
//<!-- 自定义search()方法,通过传参的形式,传递给search方法 在这个方法中通过for循环,把符合条件的数据保存到一个新数组中返回-->
                <tr v-for="item in search(keywords)" :key="item.id">
                    <td>{{item.id}}</td>
                    <td v-text="item.name"></td>
                    <td>{{item.time|dateFormat('')}}</td>
                    //<!-- 根据id删除 -->
                    <td><a href="" @click.prevent="del(item.id)">删除</a></td>
                </tr>
            </tbody>
        </table>
    </div>
new Vue({
        el: '#day1',
        data: {
            id: '',
            name: '',
            keywords: '',
            list: [
                { id: 1, name: '李四1', time: new Date() },
                { id: 2, name: '李四2', time: new Date() },
                { id: 3, name: '李四3', time: new Date() },
                { id: 4, name: '李四4', time: new Date() },
            ]
        },
        methods: {
            add() {//添加方法
                this.list.push({ id: this.id, name: this.name, time: new Date() })
                // 添加了要清空input的数据
                this.id = this.name = "";
            },
            del(id) {//删除
                // //根据id删除
                // this.list.some((item, i) => {
                //     if (this.id = id) {
                //         this.list.splice(i, 1);// 根据id查找索引,找到索引,直接调用数组splce方法删除
                //         // 终止后续循环
                //         return true;
                //     }
                // })
                // 删除方法二
                var index = this.list.findIndex(item => {
                    if (item.id == id) {
                        // 终止后续循环
                        return true;
                    }
                })
                this.list.splice(index, 1);
                console.log(index);
            },
            search(keywords) {//根据关键字,进行数据搜索
                // var newList = [];
                // this.list.forEach(item => {
                //     if (item.name.indexOf(keywords) != -1) {
                //         newList.push(item);
                //     }
                // })
                // return newList;

                // 方法二
                // forEach,some,filter,dindIndex都是素组的新方法
                return this.list.filter(item => {
                    if (item.name.includes(keywords)) {
                        return item;
                    }
                });
            }
        },
    });

定义组件:

<h1>定义全局过滤器</h1>
    <div class="filter">
        //<!-- sgFormat('青青+1')括号里面是传递参数,可传递多个 -->
        <p>{{msg|msgFormat('青青+1')}}</p>
    </div>
      <h1>定义私有过滤器</h1>
      <div id="day3">
      <h1 v-color="'green'">{{time|dateFormat}}</h1>
  </div> </div>
  // 过滤器的使用
    // 1、只能应用于v-bind和mustache(插值表达式{{}})
    // 2、格式:{{name|nameope}}
    // 3、定义全局过滤器 Vue.filter('过滤器名称',function (){})
    Vue.filter('msgFormat', function (msg, arg) {
        return msg.replace(/清清/g, arg)
    })
    new Vue({
        el: '.filter',
        data: {
            msg: '我是我是彭清清我是我是彭清清'
        },
        methods: {}
    })
    // 定义私有过滤器
    new Vue({
        el: '#day3',
        data: {
            time: new Date(),
        },
        methods: {
        },
        // 全局指令带s,私有指令不带s
        filters: {//定义私有过滤器,有两个条件:过滤器名称和处理函数,调用的时候采用就近原则,如果私有过滤器和全局过滤器的名称一致,优先调用私有
            dateFormat: function (dateStr, timePattern = "") {
                var time = new Date(dateStr);
                var year = time.getFullYear();
                // month 从0开始
                var month = time.getMonth() + 1;
                var day = time.getDate();
                if (timePattern.toLowerCase() == 'yyyy-mm-dd') {
                    return `${year}-${month}-${day}`;
                } else {
                    var hour = time.getHours();
                    var minutes = time.getMinutes();
                    var seconds = time.getSeconds();
                    return `${year}-${month}-${day}  ${hour}:${minutes}:${seconds}----`;
                }
            }
        },
    })
 Vue.config.keyCodes.f2 = 113;//自定义按键修饰符
    Vue.directive('focus', {// 自定义全局指令获取焦点  注意:参数1:指令名称 :定义的时候不需要加v-前缀,调用的时候必须加v-
        // 参数2:是一个对象,
        bind: function (el) {//每当指令绑定到元素上的时候,会执行这个函数
            // 在每一个函数中,第一个参数永远是el,表示被绑定指令的元素,这个元素是原始的js对象
        },
        inserted: function (el) {//插入到DOM的时候,执行这个函数
            el.focus()
        },
        updated: function () {//每当vNode更新的时候执行
        }
    })
    Vue.directive('color', {//自定义全局设置字体颜色的指令}
        bind: function (el, binding) {
            //el.style.color = 'red'//样式只要通过指令不绑定给了元素,不管有没有插入到页面中,这个元素肯定有了内联样式
            el.style.color = binding.value;
        }
        // 和样式相关的在bind设置就可以,和行为相关的在inserted设置,防止js行为不生效
    })
    // 定义全局格式化时间
    Vue.filter('dateFormat', function (dateStr, timePattern = "") {
        var time = new Date(dateStr);
        var year = time.getFullYear();
        // month 从0开始
        var month = time.getMonth() + 1;
        var day = time.getDate();
        // 如果传递timePattern参数不等于yyyy-mm-dd,就把他转化为小写,如果是yyyy-mm-dd格式的
        // 说明显示的是年月日否则就是完整的时间
        if (timePattern.toLowerCase() == 'yyyy-mm-dd') {
            return `${year}-${month}-${day}`;
        } else {
            var hour = time.getHours();
            var minutes = time.getMinutes();
            var seconds = time.getSeconds();
            return `${year}-${month}-${day}  ${hour}:${minutes}:${seconds}`;
        }
    })

 定义私有指令:指令名称是驼峰命名的,由于html不认识驼峰命名,所以引用的时候用-连接起来

html代码如下:

<div id="day3">
   <h1 v-font-Style="'italic'" v-font-Size="30">{{time|dateFormat}}</h1>
</div>

vue代码如下:

new Vue({
        el: '#day3',
        data: {
            time: new Date(),
        },
        methods: {
        },
        // 全局指令带s,私有指令不带s 
        filters: {//定义私有时间过滤器,有两个条件:过滤器名称和处理函数,调用的时候采用就近原则,如果私有过滤器和全局过滤器的名称一致,优先调用私有
            dateFormat: function (dateStr, timePattern = "") {
                var time = new Date(dateStr);
                var year = time.getFullYear();
                // month 从0开始
                var month = time.getMonth() + 1;
                var day = time.getDate();


                if (timePattern.toLowerCase() == 'yyyy-mm-dd') {
                    return `${year}-${month}-${day}`;
                } else {
                    var hour = time.getHours();
                    var minutes = time.getMinutes();
                    var seconds = time.getSeconds();
                    return `${year}-${month}-${day}  ${hour}:${minutes}:${seconds}----`;
                }
            }
        },
        directives: {//定义私有指令
            'fontStyle': {
                bind: function (el, binding) {
                    el.style.fontStyle = binding.value;
                }
            },
            'fontSize': function (el, binding) {//这个函数等同于把代码写到了bind和update中
                el.style.fontSize = parseInt(binding.value) + 'px';
            }
        }
    });

 vue动画:

(1)、使用过渡类名定义动画

HTML代码如下:

<div id="app">
        <input type="button" value="toggle" @click="show=!show">
        //<!-- 使用transition把需要动画的元素包裹起来 这是vue官方提供的-->
        <transition name="my">
           // <!--使用name属性来定义前缀来自定义动画,使用的时候.my-enter-->
            //<!-- 点击按钮让小圆展示出来,v-show 和v-if都行-->
            <h3 class="circle" v-show="show">这是一个动画</h3>
        </transition>
</div>

样式代码如下:

    //* 自定义两组样式,来控制transition内部的元素实现动画 */
        .my-enter,
       //*这是一个时间点,是进入之前元素的起始状态,此时还没有开始进入*/
        v-leave-to {
           //*这是一个时间点,是离开之后,离开的终止状态,此时动画已结束*/
            opacity: 0;
            transform: translateX(150px);
        }
        .my-enter-active,
       / /*入场动画的时间段*/
        .my-leave-active {
        / /*离场动画的时间段*/
            transition: all 1s ease;
        }

vue代码如下:

new Vue({
        el: '#app',
        data: {
            show: false
        },
        methods: {},
    });

(2)、使用第三方css类库定义动画

<div id="app">
        <input type="button" value="toggle" @click="show=!show">
        //<!-- :duration="400"统一设置动画的出场,和入场动画时长 -->
        //<!-- :duration="{enter:200,leave:400} 分别设置动画的出场,和入场动画时长-->
        <transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut" :duration="400">
            <h3 class="circle" v-show="show">这是一个动画</h3>
        </transition>
        //<!-- 把animated放在元素上 -->
        <transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="{enter:200,leave:400}">
            <h3 class="circle" v-show="show" class="animated">这是一个动画</h3>
        </transition>
    </div>

 (3) 、钩子函数实现半场动画(只需要进入动画或是只需要出场动画)

例子:小球动画

 HTML 代码如下:

<div id="app">
        <input type="button" value="toggle" @click="show=!show">
        <transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
            <h3 class="circle" v-show="show"></h3>
        </transition>
</div>

样式代码如下:

 .circle {
             20px;
            height: 20px;
            border-radius: 50%;
            background-color: olive;
        }

vue代码如下:

 new Vue({
        el: '#app',
        data: {
            show: false
        },
        methods: {
            //动画钩子函数的第一个参数是el,不是要执行动画的DOM元素,是原生的jsDOM对象,可以认为是通过document.getElementById获取到的
            beforeEnter(el) {//这个函数是表示,动画入场前,此时动画未开始,在这里设置动画之前的起始样式
                el.style.transform = "translate(0,0)"//设置小球开始前的动画
            },
            enter(el,done) {//这个函数是表示,动画开始之后的样式,可以设置小球完成后的结束状态
                el.offsetWidth;//这句话没有实际应用,强制动画刷新,不设置动画就不会出来,有height,left,top
                el.style.transform = "translate(150px,150px)";
                el.style.transition = "all 1s ease";
                done();//这个是afterEnter函数的引用,加上会停留一会在消失,不然就会立即消失
            },
            afterEnter(el) {//这个函数是表示,动画完成之后
                this.show=!this.show;
            }
        },
    });

 (4)、使用transition-group实现列表组动画

HTML代码如下:

 <div id="app">
        <div>
            <label>Id:<input type="text" v-model="id"></label>
            <label>Name:<input type="text" v-model="name"></label>
            <input type="button" value="添加" @click="add">
        </div>
        //<!-- <ul> -->
       // <!-- 实现列表过渡的时候,如果过渡的元素是v-for循环渲染的,不能使用transition包裹,使用transition-group -->
        //<!-- 如果用v-for循环创建动画,必须为每一个元素设置:key属性 -->
        <transition-group appear tag="ul">
            //<!--给transition-group添加appear属性,给页面刚展示出来入场效果-->
            <li v-for="item in list" :key="item.id" @click="del">
                {{item.id}}---{{item.name}}
            </li>
        </transition-group>
        //<!--  由于transition-group默认会渲染为span元素,span里面包含li是不符合w3c规范,所以要设置tag属性为ul-->
        //<!-- </ul> -->
    </div>

样式代码如下:

 li {
            list-style: none;
            border: orange 1px solid;
            margin-right: 5px;
            line-height: 30px;
            font-size: 12px;
             100%;
        }

        //* 进入动画 */
        .v-enter,
        .v-leave-to {
            opacity: 0;
            transform: translateX(15px);
        }

        .v-enter-active,
        .v-leave-active {
            transition: all 1s ease;
        }

        li:hover {
            background-color: olivedrab;
            transition: all 0.4s ease;
        }

       //* 离开动画 .v-move/v-leave和.v-leave配合使用*/
        .v-move {
            /*v-leave也行*/
            transition: all 1s ease;
        }

        .v-leave-active {
            position: absolute;
        }

vue代码如下:

new Vue({
        el: '#app',
        data: {
            id: '',
            name: '',
            list: [
                { id: 1, name: '李四1' },
                { id: 2, name: '李四2' },
                { id: 3, name: '李四3' },
                { id: 4, name: '李四4' },
            ]
        },
        methods: {
            add() {
                console.log("a");
                this.list.push({ id: this.id, name: this.name })
            },
            del(i) {//删除
                this.list.splice(i, 1);
            }
        },
    });

 vue组件化和模块化:

什么是组件组建是为了拆分实例的代码量,能够让我们以不同的主见来划分不同的功能模块,将来我们需要什么样的功能就可以去调用对应的组件

组件化和模块化的不同:
模块化是从代码逻辑的角度进行划分的,方便代码分量开发,保证每个功能模块的职能单一
组件化是从ui界面的角度进行划分的,前端的组件转变,uI组件的重用

(1)、分别使用Vue.extend和Vue.component创建组件

<div id="app">
    //<!-- 如果要使用组件,直接把组件的名称以HTML标签形式引入到页面中 -->
    <my-Com1></my-Com1>
</div>
// 1、使用Vue.extend创建的全局组件
    var com1 =Vue.extend({
        template:'<h3>这是使用Vue.extend创建的全局组件</h3>'//通过template属性指定组件要展示的HTML结构
    });
    // 2、Vue.component('组件名称',创建出来的组件模块对象)
    Vue.component('myCom1',com1)//注意:组件名称是驼峰命名法,引用的时候两个单词之间要使用—连接
    // 创建vue实例
    new Vue({
        el:'#app',
        data:{}
    });

(2)、使用对象字面量的形式创建

// Vue.component第一个参数:组件名称,将来引入的时候就使用标签的形式引入,第二个参数:Vue.extend创建的组件,其中template属性就是组件要展示的HTML内容
    Vue.component('myCom1',Vue.extend({
        template:'<h3>这是使用Vue.extend创建的全局组件</h3>'
    }));
    // 上面的方式还可以简化,使用对象字面量的形式创建
    Vue.component('myCom1',{
        // 注意:无论使用哪种方式创建组件,属性template指定的模板内容有且只有唯一一个根元素,要用div包裹起来
        template:'<div><h3>这是使用Vue.extend创建的全局组件<span>123</span></h3></div>'
    });
    // 创建vue实例
    new Vue({
        el:'#app',
        data:{}
    });

(3)、把模板template单独的抽取出去

<body>
    <div id="app"> 
        <my-Com1></my-Com1>
    </div>
    //<!-- 在被控制的#app外面,使用template元素,定义组件HTML结构 -->
    <template id="com1">
        <div>
            <h3>这是通过template元素,在外部定义的组件结构,这个方式有代码提示</h3>
        </div>
    </template>
</body>
</html>
<script>
    Vue.component('myCom1', {
        template: '#com1'
    });
    // 创建vue实例
    new Vue({
        el: '#app',
        data: {}
    });
</script>

 以上都是全局的

(4)、使用components创建私有组件

<div id="app"> 
     <login></login>
</div>
// 创建vue实例 new Vue({ el: '#app', data: {}, methods: {}, components:{ login:{ template:'<h3>这是通过template元素</h3>' } } });

(5)、组件中的data:组件中可以有自己的data,但和实力中的data不一样,组件中的data要为一个函数,并且返回的是一个对象,但使用方式是一样的

Vue.component('myCom1', {
        template: '<h3>这是全局组件--{{msg}}</h3>',
        data:function (){
            return {
                msg:'这是组件中定义的data数据'
            };
        }
    });

 (6)、为什么组件的data要为一个function,下面用实例演示

 <div id="app">
        <my-Com1></my-Com1>
        <my-Com1></my-Com1>
        <my-Com1></my-Com1>
    </div>
    <template id="day">
        <div>
            <input type="button" value="+1" @click="add">
            <h3>{{count}}</h3>
        </div>
    </template>
// var dataObject={count: 0};
    Vue.component('myCom1', {
        template: '#day',
        data: function () {
            return {
                count: 0
                // dataObject//如果把对象定义在外面,当调用多次组件的时候,点击一个按钮其他按钮会受到影响
            };
        },
        methods: {
            add() {
                this.count++;
            }
        },
    });
    // 创建vue实例
    new Vue({
        el: '#app',
        data: {},
        methods: {},
    });

组件的切换:

 (1)、v-if和v-else实现很多组件的切换,缺点是:只能切换两个,当有多个的时候就不行

<div id="app">
        <a href="" @click.prevent="show=true">登入</a>
        <a href=""  @click.prevent="show=false">注册</a>
        <login v-if="show"></login>
        <register v-else="show"></register>
</div>
Vue.component('login', {
        template: '<h3>登入组件</h3>',
    });
    Vue.component('register', {
        template: '<h3>注册组件</h3>',
    });
    // 创建vue实例
    new Vue({
        el: '#app',
        data: {
            show:true
        },
        methods: {},
    });

(2)、使用component切换多个组件

 <div id="app">
        <a href="" @click.prevent="comName='login'">登入</a>
        <a href="" @click.prevent="comName='register'">注册</a>
        //<!-- vue提供的component来展示对应名称的组件,component是一个占位符,is属性指定要展示的组件的名称 -->
        <component :is="comName"></component>
      // <!-- 属性绑定会把后面的当作表达式解析 -->
 </div>
// 组件名称是字符串,:is属性绑定会把后面的当作表达式解析,并不是真正的字符串,所以'login'要用单引号包起来
    Vue.component('login', {
        template: '<h3>登入组件</h3>',
    });
    Vue.component('register', {
        template: '<h3>注册组件</h3>',
    });
    // 创建vue实例
    new Vue({
        el: '#app',
        data: {
            comName:'login'//这个comName是 :is属性绑定的组件名称,默认展示login
        },
        methods: {},
    });

(3)、组件切换应用动画

<div id="app">
        <a href="" @click.prevent="comName='login'">登入</a>
        <a href="" @click.prevent="comName='register'">注册</a>
        //<!-- mode属性:设置组件切换的模式,out-in是上一个消失了才消失下一个 -->
        <transition mode="out-in">
            <component :is="comName"></component>
        </transition>
</div>
/* 进入动画 */
        .v-enter,
        .v-leave-to {
            opacity: 0;
            transform: translateX(15px);
        }
//出场动画
        .v-enter-active,
        .v-leave-active {
            transition: all 1s ease;
        }

 父组件和子组件传递值的data和props区别

// 子组件,默认无法访问到副总监的data上的数据和methods中的方法,副组件可以在引用纸组件的时候,通过绑定v-bind的形式,
    // 把需要传递给子组件的数据以属性绑定的形式传递到子组件的内部,供子组件使用
    Vue.component('com1', Vue.extend({
        template:'<h1>hekk</h1>'
    }))
    new Vue({
        el: '#app',
        // data上的数据都是可读可写的
        data: {//注意:子组件的data数据,不是通过父组件传递过来的,而是子组件自身有的,如:子组件通过ajax,请求回来的数据,都可以在data上定义
            msg:'这是父组件中的数据'
        },
        methods: {},
        components:{
            com1:{
                template:'<h1 >这是子组件---{{parentmsg}}</h1>',
                // 注意:组件中的所有props中的数据都是通过父组件传递给子组件的
                // props中的数据是只读的,无法重新复制被修改
                props:['parentmsg']//把父组件传递过来的parentmsg属性,先在props数组中定义一下,才能使用
            }
        }
    });

子组件通过事件调用向父组件传值

var com1 = {
        template: '#com',
        data() {
            return {
                sonmsg: { name: "李四", age: 13 }
            }
        },
        methods: {
            // 子组件的点击事件
            myclick() {
                // $emit 英文意思是触发,发射
                this.$emit('func', this.sonmsg)//调用父组件的方法并传递参数,this.sonmsg传递给父组件
            },
        },
    }
    new Vue({
        el: '#app',
        data: {
            datamsg:null
        },
        methods: {
            show(data) {
                console.log("调用了父组件的方法");
                this.datamsg=data;
            }
        },
        components: {
            com1
        }
    });

 使用ref获取dom元素和组件引用

<!-- 使用ref获取dom元素和组件引用 -->
    <div id="app">
        <input type="button" value="获取元素" @click="getElement">
        <h3 id="myh3" ref="myh3">haha</h3>
        <login ref="loginref"></login>
    </div>
</body>
 //上面是HTML
<script>
    var login = {
        template: '<h3>login</h3>',
        data() {
            return {
                msg: 'sonmsg'
            }
        },
        methods: {
            show() {
                console.log('调用了子组件的方法')
            }
        },
    }
    new Vue({
        el: '#app',
        data: {},
        methods: {
            getElement() {
                // console.log(document.getElementById('myh3').innerHTML);
                // console.log(this.$refs.myh3.innerText);//ref是reference的缩写
                console.log(this.$refs.loginref.msg);//用ref输出组件的信息
                this.$refs.loginref.show();//调用组的方法
            }
        },
        components: {
            login
        }
    });

vue路由

后端路:由对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源

前端路由:对于当页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时hash有一个特点,HTTP请求中不会包含hash相关的内容,所以当页面跳转主要用hash实现,在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由

 (1)、router-link、router动画、路由高亮使用

HTML代码:

 <div id="app">
        //<!-- <a href="#/login">登入</a> -->
        //<!-- <a href="#/register">注册</a> -->
        //<!-- router-link默认渲染的是a标签,用router-link就不用加# -->
        <router-link to="/login" tag="span">登入</router-link>
        //<!--tag="span"渲染为span标签-->
        <router-link to="/register">注册</router-link>
        
        //<!-- router-view是vue-router提供的元素,用来当占位符,路由规则匹配到的组件展示在这里 -->
        //<!--  给路由加动画 -->
        <transition mode="out-in">
            <router-view></router-view>
        </transition>
</div>

样式代码:

 //* 设置当前展示的样式,路由高亮(路由默认的,自带的) */
        .router-link-active {
            color: olive;
            font-weight: 500;
            text-decoration: underline;
            font-size: 30px;
        }

        //* 自定义的路由高亮 */
        .myactive {
            color: olive;
            font-weight: 500;
            text-decoration: underline;
            font-size: 30px;
        }
        //* 路由动画 */
        .v-enter,
        .v-leave-to{
            opacity: 0;
            transform: rotateX(140px);
        }
        .v-enter-active,
        .v-leave-active{
            transition: all 1s ease;
        }

vue代码:

var login = {
        template: '<h1>login</h1>'
    }
    var register = {
        template: '<h1>register</h1>'
    }
    // 创建一个路由对象,当导入vue-router包之后,在windows全局对象中就有了一个路由的构造函数叫做VueRouter
    var routerObj = new VueRouter({//new 一个路由对象,可以为一个构造函数,传递一个配置对象
        // 
        routes: [//这个配置对象的routes表示:路由匹配规则,
            // 每个匹配规则有两个属性,一:path,表示监听哪个路由链接地址
            // 二:component表示,如果路由是前面匹配到的path,则表示component属性对应的哪个组件
            // 注意:component属性值必须是一个组件对象,不能是组件的引用名称
            { path: '/', redirect: '/login' },//手动修改hash值
            { path: '/login', component: login },
            { path: '/register', component: register },
        ],
        linkActiveClass: 'myactive'//自定义自己的高亮样式
    })
    new Vue({
        el: '#app',
        data: {},
        methods: {},
        router: routerObj//将路由规则对象注册到我们的vm实例上,然后展示对应的组件
    });

 (2)、路由规则中定义参数

2.1、使用query方式传递参数

<div id="app">
        //<!-- 如果在路由中使用查询字符串,给路由传递参数则不需要修改路由规则的path属性,就是 { path: '/', redirect: '/login' }, -->
        //<!-- to="/login?id=10&&name=李思",传递参数,可以传递多个 -->
        <router-link to="/login?id=10&name=李思">登入</router-link>
        <router-link to="/register">注册</router-link>
        <router-view></router-view>
</div>
var login = {
        template: '<h1>login---{{$route.query.id}}---{{$route.query.name}}</h1>',//this可以省略
        data(){
            return{
                msg:'124'
            }
        },
        created() {// 组件生命周期钩子函数
            console.log(this.$route);//$route和$ref差不多
            console.log(this.$route.query.id);//输出id里面的值。
        },
    }
    var register = {
        template: '<h1>register</h1>'
    }
    var routerObj = new VueRouter({
        routes: [
            { path: '/login', component: login },
            { path: '/register', component: register },
        ],
    });
    new Vue({
        el: '#app',
        data: {},
        methods: {},
        router: routerObj,//属性名和属性值一样可以简化,就是new出来的router的名称和router一样只用写一个,现在这个router: routerObj不一样
    });

2.2、使用params方式传递路由参数

<div id="app">
        //<!-- 使用params传递参数 -->
        <router-link to="/login/10/lisi">登入</router-link>
        <router-link to="/register">注册</router-link>
        <router-view></router-view>
</div>
<script>
    var login = {
        template: '<h1>login---{{$route.params.id}}--{{$route.params.name}}</h1>',//this可以省略
        data(){
            return{
                msg:'124'
            }
        },
        created() {// 组件生命周期钩子函数
            console.log(this.$route.params.id);
        },
    }
    var register = {
        template: '<h1>register</h1>'
    }
    var routerObj = new VueRouter({
        routes: [
            { path: '/login/:id/:name', component: login },//:id解析id,:name解析name,通过URL地址,可以有多个参数
            { path: '/register', component: register },
        ],
    });
    new Vue({
        el: '#app',
        data: {},
        methods: {},
        router: routerObj,//属性名和属性值一样可以简化,就是new出来的router的名称和router一样只用写一个,现在这个router: routerObj不一样
    });

使用children实现路由嵌套

HTML代码如下:

<body>
    <div id="app">
        <router-link to="/account">account</router-link>
        <router-view></router-view>
    </div>
    <template id="com">
        <div>
            <h1>这是Account组件</h1>
            <router-link to="/account/login">登入</router-link>
            <router-link to="/account/register">注册</router-link>
            <router-view></router-view>
        </div>
    </template>
</body>

vue代码如下:

<script>
    var account = {
        template: '#com',
    }
    var login = {
        template: '<h3>登入</h3>',
    }
    var register = {
        template: '<h3>注册</h3>',
    }
    var router = new VueRouter({
        routes: [
            { path: '/account',
             component: account ,
             children:[
                 {path: 'login', component: login },//使用children属性前面,不带/,否则永远以跟路劲请求,不方便用户理解URL地址
                 {path: 'register', component: register },
             ]
            },
            // { path: '/account/login', component: login },
            // { path: '/account/register', component: register },
        ]
    })
    new Vue({
        el: '#app',
        router//属性名和属性值一样可以简化,就是new出来的router的名称和router一样只用写一个
    });