本地引入vue.js文件

<script src="./vue.js" type="text/javascript"></script>

数据绑定的几种方式
Html:
数据绑定①

<div id="demo">{{msg}}</div>

数据绑定②

<div id="demo" v-html="msg"></div>

数据绑定③

<div id="demo" v-text="msg"></div>

js

    var demo=new Vue({
        el:'#demo',
        data:{
            msg:'hello world!'
        },
        methods:{
            demoClick:function(){
                alert('谢谢你的点击');
            }
        }
    })

Vue事件绑定
html

<div id="demo" v-on:click="demoClick">{{msg}}</div>

js

    var demo=new Vue({
        el:'#demo',
        data:{
            msg:'hello world!'
        },
        methods:{
            demoClick:function(){
                this.msg="hello~~";
            }
        }
    })

属性绑定和双向数据绑定
属性绑定

<div id="root">
 <div v-bind:title="title">hello world</div>
</div>

双向数据绑定(v-model只能用在表单元素中)

<div id="root">
<input type="text" v-model="content"/>
<div>{{content}}</div>
</div>

js部分

  <script>
       new Vue({
           el:"#root",
           data:{
               title:'this is the vue title',
               content:'文本框的内容'
           }
       })
   </script>

计算属性与侦听器
html

   <div id="root">
      名:<input type="text" v-model="firstName"/>
       姓:<input type="text" v-model="lastName"/>
      <div>{{firstName}}{{lastName}}</div>
       <div>{{fullName}}</div>
       <div>{{count}}</div>
   </div>

js

       new Vue({
           el:'#root',
           data:{
               firstName:'',
               lastName:'',
               count:0
           },
           computed:{   //计算属性
               fullName:function(){
                   return this.firstName+this.lastName;
               }
           },
           watch:{    //侦听
               firstName:function(){
                   this.count++;
               },
               lastName:function(){
                   this.count++;
               }
           }
       });

条件渲染
html

<div id="root">
    <!-- 当点击按钮时候,v-if元素直接从dom树消失,v-show只是将style属性修改成display:none;再次点击按钮的时候,都可以重新恢复;<template> 元素当做包装元素,并在上面使用 v-if,最终的渲染结果不会包含它-->
    <div v-if="show">hello world</div>
    <div v-show="show">hello world</div>
    <template v-if="show">
        hello world~
    </template>
    <button v-on:click="handleClick">显示或者隐藏</button>
</div>

js

    new Vue({
       el:'#root',
        data:{
           show:true,
        },
        methods:{
           handleClick:function(){
               this.show=!this.show;
           }
        }
    });

列表渲染
html

    <ul>  <!--三种渲染方法-->
        <li v-for="item of list">{{item}}</li>
        <li v-for="item of list" :key="item">{{item}}</li>
        <li v-for="(item,index) of list" :key="index">{{item}}</li>
    </ul>

js

    new Vue({
       el:'#root',
        data:{
            list:[1,2,3]
        },
        methods:{
           handleClick:function(){
               this.show=!this.show;
           }
        }
    });


v-cloak指令 解决刷新或者加载出现闪烁

<head>
    <meta name="viewport" content="width=device-width" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Vue</title>
    <style>
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>
<div id="message">
    <div v-cloak>
        {{msg}}
    </div>
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    var vue=new Vue({
        el:"#message",
        data:{
            msg:'这是一条新消息'
        }
    });
</script>

v-text指令

<body>
<div id="message">
    <!--
    v-text不存在闪烁问题
    v-text会覆盖元素中原来的内容,而插值表达式只会替换自己的这个占位符,不会把整个元素内的内容清空
    v-html类似v-text
    -->
    <div v-text="msg">
        ++++++++++++++
    </div>
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    var vue=new Vue({
        el:"#message",
        data:{
            msg:'这是一条新消息'
        }
    });
</script>

v-bind指令 缩写:

<body>
<div id="container">
    <!--无效-->
   <button title="{{msg}}">按钮1</button>
    <!--有效-->
   <button v-bind:title="msg">按钮2</button>
    <!--有效-->
   <button :title="msg">按钮3</button>
   <!--有效-->
   <button :title="msg+'字符串'">按钮4</button>
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    var vue=new Vue({
        el:"#container",
        data:{
            msg:'按钮标题'
        }
    });
</script>

v-on 缩写@

<div id="container">
   <button v-on:click="alertFn">按钮</button>
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    var vue=new Vue({
        el:"#container",
        data:{
            msg:'按钮标题'
        },
        methods:{
            alertFn:function(){
                alert('你点击了按钮');
            }
        }
    });
</script>

跑马灯制作

<div id="container">
    <button @click="lang">浪起来</button>
    <button @click="stop">稳住</button>
    <div>{{msg}}</div>
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    var vue=new Vue({
        el:"#container",
        data:{
            msg:'猥琐发育,别浪~',
            intervalId:null
        },
        methods:{
            lang:function(){
/*                var _this=this;
                setInterval(function(){
                    var msg=_this.msg;
                    var str=msg.substring(0,1);  //截取字符串
                    var otherStr=msg.substring(1);             //剩余字符串
                    _this.msg=otherStr+str;
                },300);*/
                //使用箭头函数
                if(this.intervalId!=null) return;
                this.intervalId=setInterval(()=>{
                    var msg=this.msg;
                    var str=msg.substring(0,1);  //截取第一个字符串
                    var otherStr=msg.substring(1);             //剩余字符串
                    this.msg=otherStr+str;
                },300);
            },
            stop:function(){
                clearInterval(this.intervalId);
                this.intervalId=null;
            }
        }
    });
</script>

事件修饰符

<!--默认点击 冒泡-->
<!--    <div @click="divClick" id="container">
        <button @click="btnClick">
            按钮
        </button>
    </div>-->
 
<!--阻止事件冒泡stop-->
<!--   <div @click="divClick" id="container">
        <button @click.stop="btnClick">
            按钮
        </button>
    </div>-->
 
<!--阻止元素默认行为prevent 点击后a标签不跳转-->
<!--<div  id="container">
<a href="http://www.baidu.com" @click.prevent="linkClick">百度一下,你就知道</a>
</div>-->
 
<!--捕获事件capture   先触发div点击事件divClick-->
<!--<div @click.capture="divClick" id="container">
    <button @click="btnClick">
        按钮
    </button>
</div>-->
 
<!--self   只有点击当前元素,才会触发事件-->
<!--<div @click.self="divClick" id="container">
    <button @click="btnClick">
        按钮
    </button>
</div>-->
 
<!--使用once只触发一次事件-->
<div  id="container">
<a href="http://www.baidu.com" @click.prevent.once="linkClick">百度一下,你就知道</a>
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    var vue=new Vue({
        el:"#container",
        data:{
        },
        methods:{
            divClick:function(){
                console.log('div点击事件');
            },
            btnClick:function(){
                console.log('按钮点击事件');
            },
            linkClick:function(){
                console.log('百度个毛线');
            }
        }
    });
</script>

简易计算器

<div id="container">
<input type="text" v-model="n1"/>
<select v-model="opt">
    <option>+</option>
    <option>-</option>
    <option>*</option>
    <option>/</option>
</select>
<input type="text" v-model="n2"/>
<button @click="caculate">=</button>
<span>{{result}}</span>
</div>
 
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    var vue=new Vue({
        el:"#container",
        data:{
            n1:0,
            opt:'+',
            n2:0,
            result:0
        },
        methods:{
            caculate:function(){
                switch (this.opt){
                    case '+':
                        this.result=(parseFloat(this.n1)+parseFloat(this.n2)).toFixed(2);
                        break;
                    case '-':
                        this.result=(parseFloat(this.n1)-parseFloat(this.n2)).toFixed(2);
                        break;
                    case '*':
                        this.result=(parseFloat(this.n1)*parseFloat(this.n2)).toFixed(2);
                        break;
                    case '/':
                        this.result=(parseFloat(this.n1)/parseFloat(this.n2)).toFixed(2);
                        break;
                }
             }
        }
    });
</script>

简易计算器2

<div id="container">
    <input type="text" v-model="n1"/>
    <select v-model="opt">
        <option>+</option>
        <option>-</option>
        <option>*</option>
        <option>/</option>
    </select>
    <input type="text" v-model="n2"/>
    <button @click="caculate">=</button>
    <span>{{result}}</span>
</div>
 
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    var vue=new Vue({
        el:"#container",
        data:{
            n1:0,
            opt:'+',
            n2:0,
            result:0
        },
        methods:{
            caculate:function(){
                var code=(parseFloat(this.n1)+this.opt+parseFloat(this.n2));
                this.result=eval(code).toFixed(2);
                }
            }
 
    });
</script>

Vue中属性绑定设置class类样式

<body>
<div id="container">
 
    <span :class="style1">数组形式</span>  <!--渲染后 <span class="italic bold">数组形式</span> -->
 
    <span :class="['red','bold',flag?'active':'']">三元表达式</span>  <!--渲染后 <span class="red bold active">三元表达式</span> -->
 
    <!--注意flag不用引号-->
    <span :class="flag?'active':''">三元表达式</span>   <!--渲染后 <span class="active">三元表达式</span> -->
 
    <!--注意flag不用引号-->
    <span :class="['red','bold',{'active':flag}]">三元表达式</span>   <!--渲染后 <span class="red bold active">三元表达式</span> -->
    <!--对象key可以加引号可以不加引号-->
    <span :class="{'red':true,bold:false,active:true}">对象</span>   <!--渲染后 <span class="red active">对象</span> -->
 
    <span :class="classObj">对象</span>   <!--效果同上-->
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    new Vue({
        el:'#container',
        data:{
            style1:['italic','bold'],
            style2:['red','bold'],
            flag:true,
            classObj:{red:true,bold:false,active:true}
        },
        methods:{
 
        }
    })
</script>

Vue中属性绑定设置class类样式

<body>
<div id="container">
    <!--font-weight不加引号 报错 - invalid expression: Unexpected token - in  {color:'red',font-weight:'bold'}-->
    <!--<span :style="{color:'red',font-weight:'bold'}">Vue通过属性为元素绑定style行内样式</span>-->
 
    <span :style="{color:'red','font-weight':'bold'}">Vue通过属性为元素绑定style行内样式</span>
    <!--渲染后 <span style="color: red; font-weight: bold;">Vue通过属性为元素绑定style行内样式</span> -->
 
    <span :style="styleObj1">Vue通过属性为元素绑定style行内样式</span>
    <!--渲染后 <span style="color: red; font-weight: bold;">Vue通过属性为元素绑定style行内样式</span> -->
 
    <span :style="[styleObj1,styleObj2]">Vue通过属性为元素绑定style行内样式</span>
    <!--渲染后 <span style="color: red; font-weight: bold; font-size: 16px;">Vue通过属性为元素绑定style行内样式</span> -->
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    new Vue({
        el:'#container',
        data:{
            styleObj1:{color:'red','font-weight':'bold'},
            styleObj2:{'font-size':'16px','font-weight':'bold'}
        },
        methods:{
        }
    })
</script>

v-for指令

<body>
<div id="container">
    <ul>
        <!--普通数组-->
        <li v-for="item in items">{{item}}</li>
        <!--渲染后
        <li>小明</li><li>小红</li><li>小狗</li>
        -->
 
        <li v-for="(item,index) in items">{{item}}{{index}}</li>
        <!--渲染后
         <li>小明0</li><li>小红1</li><li>小狗2</li>
        -->
 
        <!--对象数组-->
        <li v-for="(item,index) in students">编号:{{index+1}}姓名:{{item.name}}性别:{{item.gender}}</li>
        <!--渲染后
        <li>编号:1姓名:小明性别:男</li><li>编号:2姓名:小红性别:男</li><li>编号:3姓名:小狗性别:公</li>
        -->
 
        <!--对象-->
        <li v-for="(item,key) in someOne">键:{{key}} 值:{{item}}</li>
        <!--渲染后
        <li>键:name 值:小明</li>
        <li>键:gender 值:男</li>
        -->
 
        <!--对象-->
        <li v-for="(item,key,index) in someOne">索引:{{index}} 键:{{key}} 值:{{item}} </li>
        <!--渲染后
        <li>索引:0 键:name 值:小明 </li>
        <li>索引:1 键:gender 值:男 </li>
        -->
 
        <!--对象-->
        <li v-for="item in someOne"> 值:{{item}}</li>
        <!--渲染后
        <li>值:小明</li>
        <li>值:男</li>
        -->
 
        <!--数字-->
        <li v-for="count in 3"> 第{{count}}个</li>
        <!--渲染后
        <li> 第1个</li>
        <li> 第2个</li>
        <li> 第3个</li>
        -->
</ul>
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
new Vue({
 el:'#container',
 data:{
     items:['小明','小红','小狗'],
     students:[
         {name:'小明',gender:'男'},
         {name:'小红',gender:'男'},
         {name:'小狗',gender:'公'}
     ],
     someOne:{
         name:'小明',
         gender:'男'
     }
 },
 methods:{
 }
})
</script>

v-if和v-show指令

<body>
<div id="ulContainer" @click="flagFn" style="height: 200px;border:1px solid black;">
   <!-- 点击后渲染 <div id="ulContainer" style="height: 200px; border: 1px solid black;"><!&ndash;&ndash;> <span style="display: none;">v-show显示</span></div>
   v-show是切换元素的display样式
   v-if是重新删除或者创建元素
   -->
    <span v-if="flag">v-if显示</span>
    <span v-show="flag">v-show显示</span>
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    new Vue({
        el:'#ulContainer',
        data:{
            flag:true
        },
        methods:{
            flagFn(){
                this.flag=!this.flag;
            }
        }
    });
</script>

效果同上

<div id="ulContainer" @click="flag=!flag" style="height: 200px;border:1px solid black;">
    <!-- 点击后渲染 <div id="ulContainer" style="height: 200px; border: 1px solid black;"><!&ndash;&ndash;> <span style="display: none;">v-show显示</span></div>
    v-show是切换元素的display样式
    v-if是重新删除或者创建元素
    -->
    <span v-if="flag">v-if显示</span>
    <span v-show="flag">v-show显示</span>
</div>
</body>
<script src="./js/vue.js" type="text/javascript" ></script>
<script>
    new Vue({
        el:'#ulContainer',
        data:{
            flag:true
        },
        methods:{
 
        }
    });
</script>

品牌的添加和删除

<head>
    <title>品牌的添加,删除</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id="ulContainer">
    <div>
        <label>品牌id<input type="text" v-model="id"></label>
        <label>品牌名字<input type="text" v-model="name"></label>
        <button @click="addBrands">添加</button>
    </div>
    <table>
        <tr>
            <th>品牌ID</th>
            <th>品牌名字</th>
        </tr>
        <tr v-for="item in brands" :key="item.id">
            <td v-text="item.id"></td>
            <td v-text="item.name"></td>
            <td><a href="" @click.prevent="del(item.id)">删除</a></td>
        </tr>
    </table>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#ulContainer',
        data: {
            id: '',
            name: '',
            keywords: '',
            brands: [
                {id: 1, name: '宝马'},
                {id: 2, name: '奔驰'}
            ]
        },
        methods: {
            //添加品牌
            addBrands(){
                var brand = {id: this.id, name: this.name};
                this.brands.push(brand);
                this.id = '';
                this.name = '';
            },
            //删除品牌
            del(id){
                //删除方法一
                //some()是对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true。
                /*               this.brands.some((item,i)=>{
                 if(item.id==id){
                 this.brands.splice(i,1);
                 return true;
                 }
                 })*/
                //删除方法二
                var delIndex = this.brands.findIndex(item => {
                        if(item.id == id)
                return true;
            })
                ;
                this.brands.splice(delIndex, 1);
            }
        }
    });
</script>

品牌的搜索功能

<head>
    <title>品牌的添加,删除和搜索</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id="ulContainer">
    <div>
        <label>品牌id<input type="text" v-model="id"></label>
        <label>品牌名字<input type="text" v-model="name"></label>
        <button @click="addBrands">添加</button>
        <label>搜索<input type="text" v-model="keywords"></label>
    </div>
    <table>
        <tr>
            <th>品牌ID</th>
            <th>品牌名字</th>
        </tr>
        <tr v-for="item in search()" :key="item.id">
            <td v-text="item.id"></td>
            <td v-text="item.name"></td>
            <td><a href="" @click.prevent="del(item.id)">删除</a></td>
        </tr>
    </table>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#ulContainer',
        data: {
            id: '',
            name: '',
            keywords: '',
            brands: [
                {id: 1, name: '宝马'},
                {id: 2, name: '奔驰'}
            ]
        },
        methods: {
            //添加品牌
            addBrands(){
                var brand = {id: this.id, name: this.name};
                this.brands.push(brand);
                this.id = '';
                this.name = '';
            },
            //删除品牌
            del(id){
                //删除方法一
                //some()是对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true。
                /*               this.brands.some((item,i)=>{
                 if(item.id==id){
                 this.brands.splice(i,1);
                 return true;
                 }
                 })*/
                //删除方法二
                var delIndex = this.brands.findIndex(item => {
                        if(item.id == id)
                return true;
            })
                ;
                this.brands.splice(delIndex, 1);
            },
            //搜索过滤
            search(){
                /*  搜索方法一
                 var newBrands=[];
                 this.brands.forEach(
                 item=>{
                 if(item.name.indexOf(this.keywords)!=-1){
                 newBrands.push(item);
                 }
                 })
                 return newBrands;*/
                 //搜索方法二
                var newBrands = this.brands.filter(item => {
                        if(item.name.includes(this.keywords))
                {   //es6方法
                    return true;
                }
            })
                return newBrands;
            }
        }
    });
</script>

vue全局过滤器

<body>
<div id="ulContainer">
    <div>
       {{msg|msgFormat1}}
       {{msg|msgFormat2('苦逼')}}   <!--过滤器传参-->
    </div>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    //所谓全局过滤器,所有的vue示例都可以共享
    /*Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。*/
    Vue.filter('msgFormat1',function(msg){
        return msg.replace(/操蛋/g,'小菜一碟');
    });
 
    Vue.filter('msgFormat2',function(msg,arg){
        return msg.replace(/操蛋/g,arg);
    });
    new Vue({
        el: '#ulContainer',
        data: {
            msg:'一个phper来学Vue,是不是有点操蛋~~'
        },
        methods: {
        }
    });
</script>

Vue自定义私有过滤器

<body>
<div id="ulContainer">
    <div>
        {{msg|msgFormat1}}
    </div>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    /*Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。*/
    Vue.filter('msgFormat1',function(msg){
        return msg.replace(/操蛋/g,'小菜一碟');   //私有自定义过滤器优先级比全局过滤器的优先级比较高
    });
    new Vue({
        el: '#ulContainer',
        data: {
            msg:'一个phper来学Vue,是不是有点操蛋~~'
        },
        methods: {
        },
        filters:{
            msgFormat1:function(msg){
                return msg.replace(/操蛋/g,'苦逼');
            }
        }
    });
</script>

Vue自定义按键修饰符

<body>
<div id="ulContainer">
    <div>
        <label>品牌id<input type="text" v-model="id"></label>
        <!--回车按enter键触发addBrands-->
        <!-- 全部的按键别名:
            .enter
            .tab
            .delete (捕获“删除”和“退格”键)
            .esc
            .space
            .up
            .down
            .left
            .right-->
        <!--<label>品牌名字<input type="text" v-model="name" @keyup.enter="addBrands"></label>-->
 
        <!--  按键别名不太全  可以采用 键盘按钮KeyCodehttps://blog.csdn.net/tanga842428/article/details/77374713来控制按钮
        <label>品牌名字<input type="text" v-model="name" @keyup.13="addBrands"></label>
        -->
 
        <!--自定义按键别名-->
        <label>品牌名字<input type="text" v-model="name" @keyup.f2="addBrands"></label>
        <button @click="addBrands">添加</button>
    </div>
    <table>
        <tr>
            <th>品牌ID</th>
            <th>品牌名字</th>
        </tr>
        <tr v-for="item in brands" :key="item.id">
            <td v-text="item.id"></td>
            <td v-text="item.name"></td>
        </tr>
    </table>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    Vue.config.keyCodes.f2=113;
    new Vue({
        el: '#ulContainer',
        data: {
            id: '',
            name: '',
            keywords: '',
            brands: [
                {id: 1, name: '宝马'},
                {id: 2, name: '奔驰'}
            ]
        },
        methods: {
            //添加品牌
            addBrands(){
                var brand = {id: this.id, name: this.name};
                this.brands.push(brand);
                this.id = '';
                this.name = '';
            }
        }
    });
</script>

Vue自定义指令

<body>
<div id="ulContainer">
   <input type="text" v-focus/>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    //Vue.directive定义全局指令 v-focus
    //参数一代表指令的名称,参数二是一个对象,可以在特定阶段执行某些操作
    Vue.directive('focus',{
        bind:function(el){         //每当指令绑定到某个元素的时候,会立即执行bind函数,只执行一次  el为一个原生的js对象
            el.focus();             //此时el还未插入dom元素中,所以调用dom操作无效
            el.style.color='red';  //样式相关的可以直接在
        },
        inserted:function(el){    //被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
            el.focus();
        },
        updated:function(el){  //所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
 
        }
    });
    new Vue({
        el: '#ulContainer',
        data: {
        },
        methods: {
 
        }
    });
</script>

Vue自定义全局指令传递参数

<body>
<div id="ulContainer">
    <input type="text" v-color="'red'"/>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    Vue.directive('color',{
        bind:function(el,binding){
            console.log(JSON.stringify(binding));    //{"name":"color","rawName":"v-color","value":"red","expression":"'red'","modifiers":{},"def":{}}
            el.style.color=binding.value;
        },
        inserted:function(el){
        },
        updated:function(el){
 
        }
    });
    new Vue({
        el: '#ulContainer',
        data: {
        },
        methods: {
 
        }
    });
</script>

Vue自定义私有指令传递参数

<body>
<div id="ulContainer">
    <input type="text" v-color="'pink'"/>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#ulContainer',
        data: {
        },
        methods: {
        },
        directives:{
            color:{
                bind:function(el,binding){
                    el.style.color=binding.value;
                }
            }
        }
    });
</script>

Vue-resource ajax请求

<body>
<div id="ulContainer">
<button @click="getData">ajax获取数据</button>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script src="./js/vue-resource.min.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#ulContainer',
        data: {
        },
        methods: {
            getData:function(){
                this.$http.get('http://ybtestshop.gouwanmei.wang/home/find/categoryList').then(response=>{
                    console.log(response);
                    console.log(response.body);    //服务器端的返回的json数据
                })
            }
        }
    });
</script>

vue-resource参考地址:https://github.com/pagekit/vue-resource
使用过渡类名实现动画

<head>
    <title>使用过渡类名实现动画</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style>
        .fade-enter-active,.fade-leave-active{
            transition: all 3s ease;
            transform: translateX(150px);
        }
        .fade-enter,.fade-leave-to{
            opacity:0;
        }
    </style>
</head>
<body>
<div id="ulContainer">
    <button @click="flag=!flag">按钮</button>
<transition name="fade">
        <div v-if="flag">过渡内容</div>
</transition>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#ulContainer',
        data: {
            flag:true
        },
        methods: {
 
        }
    });
</script>

使用animate.css实现动画

<head>
    <title>使用animate.css实现动画</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link href="./css/animate.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<div id="ulContainer">
    <button @click="flag=!flag">按钮</button>
    <transition
            enter-active-class="animated bounceIn"
            leave-active-class="animated bounceOut"
            :duration="{enter:550,leave:900}"
    >
        <div v-if="flag">过渡内容</div>
    </transition>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#ulContainer',
        data: {
            flag:true
        },
        methods: {
 
        }
    });
</script>

使用钩子函数实现动画

<body>
<div id="ulContainer">
    <button @click="flag=!flag">快进车里来</button>
    <transition
            v-on:before-enter="beforeEnter"
            v-on:enter="enter"
            v-on:after-enter="afterEnter"
    >
        <div v-if="flag" style="background-color:pink;border-radius:50%;width:50px;height:50px;"></div>
    </transition>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#ulContainer',
        data: {
            flag:false
        },
        methods: {
            beforeEnter(el){
                el.style.transform="translate(0,0)";
            },
            enter(el,done){
                el.offsetWidth;   //
                el.style.transform="translate(300px,300px)";
                el.style.transition="all 5s ease";
                done();     //立刻消失需要用   done()是afterEnter的引用
            },
            afterEnter(el){
                this.flag=false;
 
            }
 
        }
    });
</script>

Vue全局自定义组件

<body>
<div id="Container">
    <!--组件如果使用驼峰注册,在引用组件时候必须用-分隔-->
<custom-com></custom-com>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
 
<script>
/*创建组件方式①
var com=Vue.extend({
    template:'<div>有心者,才有所累;无心者,多无所谓</div>'
});
Vue.component('customCom',com);
*/
 
/*创建组件方式①
    Vue.component('customCom',Vue.extend({
        template:'<div>有心者,才有所累;无心者,多无所谓</div>'
    }));
*/
 
/*创建组件方式②
Vue.component('customCom',{
    template:'<div>有心者,才有所累;无心者,多无所谓</div>'
});*/
 
//注意:组件的模板必须包含在一个根元素中
 
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
 
        }
    });
</script>
<body>
<div id="Container">
    <custom-com></custom-com>
</div>
<template id="temp">
    <div>有心者,才有所累;无心者,多无所谓</div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
 
<script>
    //创建组件方式③
    Vue.component('customCom',{
        template:'#temp'
    });
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
 
        }
    });
</script>

Vue定义私有组件

<head>
    <title>定义私有组件</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id="Container">
    <custom-com></custom-com>
</div>
<div id="Container2">
    <!--无法使用私有组件-->
    <custom-com></custom-com>
</div>
<template id="temp"><div>有心者,才有所累;无心者,多无所谓</div></template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
 
<script>
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
        },
        components:{
            customCom: {
                template:'#temp'
            }
        }
    });
    new Vue({
        el: '#Container2',
        data: {
        },
        methods: {
        }
    });
</script>

Vue全局组件中data的使用

<body>
<div id="Container">
    <custom-com></custom-com>
</div>
<template id="temp">
    <!--组件中的数据使用类似vue实例中的数据-->
    <div>有心者,才有所累;无心者,多无所谓{{attach}}</div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    Vue.component('customCom',{
        template:'#temp',
        data:function(){    //值为一个函数,返回一个对象
            return {
                attach:'这是附加数据'
            }
        }
    });
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
 
        }
    });
</script>

登录注册组件的切换

<body>
<div id="Container">
    <a href="" @click.prevent="login">登录</a>
    <a href="" @click.prevent="register">注册</a>
    <login v-if="flag"></login>
    <register v-else></register>
</div>
<template id="login">
    <div>这是登录页面</div>
</template>
<template id="register">
    <div>这是注册页面</div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
 
<script>
 
    Vue.component('login',{
        template:'#login'
    });
 
    Vue.component('register',{
        template:'#register'
    });
    new Vue({
        el: '#Container',
        data: {
            flag:true
        },
        methods: {
            login(){
                this.flag=true;
            },register(){
                this.flag=false;
            }
 
        }
    });
</script>

登录注册组件的切换

<body>
<div id="Container">
    <a href="" @click.prevent="login">登录</a>
    <a href="" @click.prevent="register">注册</a>
    <!--component是一个占位符 用来指定组件的名称-->
    <component :is="comName"></component>
 
</div>
<template id="login">
    <div>这是登录页面</div>
</template>
<template id="register">
    <div>这是注册页面</div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
 
<script>
 
    Vue.component('login',{
        template:'#login'
    });
 
    Vue.component('register',{
        template:'#register'
    });
    new Vue({
        el: '#Container',
        data: {
            comName:'login'
        },
        methods: {
            login(){
                this.comName='login';
            },register(){
                this.comName='register';
            }
 
        }
    });
</script>

登录注册组件的动画切换

<head>
    <title>登录注册组件的动画切换</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style>
        .v-enter,.v-leave-to{
            opacity:0;
            transform:translateX(150px);
        }
        .v-enter-active,.v-leave-active{
            transition:all 0.5s ease;
        }
    </style>
</head>
<body>
<div id="Container">
    <a href="" @click.prevent="login">登录</a>
    <a href="" @click.prevent="register">注册</a>
    <transition mode="out-in">
    <!--component是一个占位符 用来指定组件的名称-->
    <component :is="comName"></component>
    </transition>
 
</div>
<template id="login">
    <div>这是登录页面</div>
</template>
<template id="register">
    <div>这是注册页面</div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
 
<script>
 
    Vue.component('login',{
        template:'#login'
    });
 
    Vue.component('register',{
        template:'#register'
    });
    new Vue({
        el: '#Container',
        data: {
            comName:'login'
        },
        methods: {
            login(){
                this.comName='login';
            },register(){
                this.comName='register';
            }
 
        }
    });
</script>

父组件向子组件传值(踩坑,传值失败)

<body>
<div id="Container">
    <custom-com v-bind:parentData="parentMsg"></custom-com>
</div>
<template id="templ">
    <div>这里是子组件的数据内容{{parentData}}</div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#Container',
        data: {
            parentMsg:'这是父组件中的数据'
        },
        methods: {
        },
        components:{
            customCom:{
                template:'#templ',
                props:['parentData']
            }
        }
    });
</script>
<!-- 浏览器控制台提示
[Vue tip]: Prop "parentdata" is passed to component <Anonymous>, but the declared prop name is "parentData". Note that HTML attributes are case-insensitive and camelCased props need to use their kebab-case equivalents when using in-DOM templates. You should probably use "parent-data" instead of "parentData".-->

解决方法
要么将v-bind:parentData中的parentData改为小写方式,props:[‘parentdata’],引用也采用小写方式。或者只改变props:[‘parentdata’]和引用为小写都可以。
父组件向子组件传值(正确方法)

<body>
<div id="Container">
    <custom-com v-bind:parentdata="parentMsg"></custom-com>
</div>
<template id="templ">
    <div>这里是子组件的数据内容{{parentdata}}</div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#Container',
        data: {
            parentMsg:'这是父组件中的数据'
        },
        methods: {
        },
        components:{
            customCom:{
                template:'#templ',
                props:['parentdata']
            }
        }
    });
</script>

子组件通过调用向父组件方法向父组件传值

<body>
<div id="Container">
    <!--向子组件传递父组件的方法
    自定义一个事件属性,子组件通过$emit触发父组件的事件
    此处不能带引号,带引号是引用eventFromParent执行的结果
    不带引号,代表引用这个方法
    -->
    <custom-com @parentevent="eventFromParent"></custom-com>
</div>
<template id="templ">
    <!--子组件调用自己的方法-->
    <div @click="eventFromSon" style="width:250px;height:250px;">这里是子组件的数据内容</div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
            //这样父组件可以获取子组件的数据
            eventFromParent:function(agr1,arg2){
                console.log('父组件的事件'+agr1,arg2)
            }
        },
        components:{
            customCom:{
                template:'#templ',
                props:['parentdata'],
                data:function(){
                    return {
                        msg:'这是来自子组件的数据'
                    }
                },
                methods:{
                    eventFromSon:function(){
                        /*调用父组件的方法 子组件可以使用 $emit 触发父组件的自定义事件
                        * emit 发出; 发射
                        * */
                        console.log(this.$emit('parentevent',this.msg,'子参数2'))
                    }
 
                }
            }
        }
    });
</script>

评论案例(父组件和子组件通信演示)

<body>
<div id="Container">
    <custom-com @loadcontent="loadContent"></custom-com>
    <table>
        <thead>
        <tr>
        <th>评论人</th>
        <th>评论内容</th>
        </tr>
        </thead>
        <tbody>
        <tr v-for="item in comments" :key="item.id">
            <td>{{item.name}}</td>
            <td>{{item.content}}</td>
        </tr>
        </tbody>
    </table>
</div>
<template id="templ">
 <div>
    <label for='userName'>用户名</label>
     <input type="text" name="userName" id="userName" v-model="userName"/><br><br>
    <label for='comment'>评论内容</label>
    <textarea name="comment" id="comment" v-model="comment"></textarea>
     <br><br>
     <button @click="submitContent">提交评论</button>
  </div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#Container',
        data: {
            comments:[
            ]
        },
        methods: {
            //这样父组件可以获取子组件的数据
            loadContent:function(){
                var commentStr=localStorage.getItem('comments');
                this.comments=JSON.parse(commentStr).reverse();  //JSON.parse() 方法用于将一个 JSON 字符串转换为对象。
            }
        },
        created:function(){
            this.loadContent();
        },
        components:{
            customCom:{
                template:'#templ',
                props:['parentdata'],
                data:function(){
                    return {
                        userName:'',
                        comment:''
                    }
                },
                methods:{
                    submitContent:function(){
                        var comments=localStorage.getItem('comments');  //localStorage中存储的是字符串
                        comments=JSON.parse(comments||'[]');
                        comments.push({id:Date.now(),name:this.userName,content:this.comment});
                        comments=JSON.stringify(comments)
                        localStorage.setItem('comments', comments);
                        this.$emit('loadcontent')
                    }
 
                }
            }
        }
    });
</script>

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

<body>
<div id="Container">
    <button @click="getInfo">获取数据</button>
    <div ref="parentDom">父组件的dom数据</div>  <!--引用父元素-->
    <custom-com id="sonCom" ref="sonCom"></custom-com>  <!--引用组件-->
</div>
<template id="templ">
  <div>子组件的数据</div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#Container',
        data: {
 
        },
        methods: {
            getInfo:function(){
                console.log(this.$refs);
                console.log(this.$refs.parentDom.innerText);  //调用父组件的dom元素
                console.log(this.$refs.sonCom.sonData);   //调用子组件的数据
                this.$refs.sonCom.sonMethod();  //调用子组件的方法
            }
        },
        components:{
            customCom:{
                template:'#templ',
                data:function(){
                    return {
                        sonData:'通过$refs调用了子组件的数据'
                    }
                },
                methods:{
                    sonMethod:function(){
                        console.log('通过$refs调用了子组件的方法')
                    }
                }
            }
        }
    });
</script>

Vue-router路由的基本使用

<body>
<a href="#/login">登录</a>
<a href="#/register">注册</a>
<div id="Container">
    <!--路由视图占位符-->
    <router-view></router-view>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<!--安装vue-router路由   引入后路径为,域名/36.html#/ -->
<script src="./js/vue-router.js" type="text/javascript"></script>
<script>
 
    //①定义 (路由) 组件
    var login={
        template:'<h3>登录界面</h3>'
    };
    var register={
        template:'<h3>注册界面</h3>'
    };
 
    //②定义路由  每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象。我们晚点再讨论嵌套路由。
    const routes = [
        { path: '/login', component: login },
        { path: '/register', component: register }
    ];
 
    //③创建 router 实例,然后传 `routes` 配置
    const router=new VueRouter({routes: routes});
 
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
        },
        router:router   //④通过 router 配置参数注入路由,从而让整个应用都有路由功能
    });
</script>

Vue-router router-link的基本使用

<head xmlns="http://www.w3.org/1999/html">
    <title>Vue-router router-link的基本使用</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style>
        /*设置当前router-link的样式*/
        .router-link-active{
            color:red;
            font-weight:bold;
        }
    </style>
</head>
<body>
<div id="Container">
    <!--router-link必须放在vue实例中 -->
    <router-link to="/login" tag="span">登录</router-link>     <!--渲染为<span class="">登录</span>-->
    <router-link to="/register">注册</router-link>         <!--渲染为<a href="#/register" class="">注册</a>-->
    <!--路由视图占位符-->
    <router-view></router-view>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<!--安装vue-router路由   引入后路径为,域名/36.html#/ -->
<script src="./js/vue-router.js" type="text/javascript"></script>
<script>
 
    //①定义 (路由) 组件
    var login={
        template:'<h3>登录界面</h3>'
    };
    var register={
        template:'<h3>注册界面</h3>'
    };
 
    //②定义路由  每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象。我们晚点再讨论嵌套路由。
    const routes = [
        { path: '/', redirect: '/login' },     //重定向,设置路由根路径展示默认页面
        { path: '/login', component: login },
        { path: '/register', component: register }
    ];
 
    //③创建 router 实例,然后传 `routes` 配置
    const router=new VueRouter({routes: routes});
 
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
        },
        router:router   //④通过 router 配置参数注入路由,从而让整个应用都有路由功能
    });
</script>

Vue-router动画

<head xmlns="http://www.w3.org/1999/html">
    <title>Vue-router动画</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style>
        /*设置当前router-link的样式*/
        .router-link-active{
            color:red;
            font-weight:bold;
        }
        .v-enter,.v-leave-to{
 
            opacity:0;
            transform:translateX(150px);
        }
        .v-enter-active,.v-leave-active{
            transition:all 1s ease;
        }
    </style>
</head>
<body>
<div id="Container">
    <!--router-link必须放在vue实例中 -->
    <router-link to="/login" tag="span">登录</router-link>     <!--渲染为<span class="">登录</span>-->
    <router-link to="/register">注册</router-link>         <!--渲染为<a href="#/register" class="">注册</a>-->
    <transition mode="out-in">
    <router-view></router-view>
    </transition>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<!--安装vue-router路由   引入后路径为,域名/36.html#/ -->
<script src="./js/vue-router.js" type="text/javascript"></script>
<script>
 
    //①定义 (路由) 组件
    var login={
        template:'<h3>登录界面</h3>'
    };
    var register={
        template:'<h3>注册界面</h3>'
    };
 
    //②定义路由  每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象。我们晚点再讨论嵌套路由。
    const routes = [
        { path: '/', redirect: '/login' },     //重定向,设置路由根路径展示默认页面
        { path: '/login', component: login },
        { path: '/register', component: register }
    ];
 
    //③创建 router 实例,然后传 `routes` 配置
    const router=new VueRouter({routes: routes});
 
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
        },
        router:router   //④通过 router 配置参数注入路由,从而让整个应用都有路由功能
    });
</script>

使用$route.query获得路由中定义参数

<head xmlns="http://www.w3.org/1999/html">
    <title>使用$route.query获得路由中定义参数</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style>
        /*设置当前router-link的样式*/
        .router-link-active{
            color:red;
            font-weight:bold;
        }
        .v-enter,.v-leave-to{
            opacity:0;
            transform:translateX(150px);
        }
        .v-enter-active,.v-leave-active{
            transition:all 1s ease;
        }
    </style>
</head>
<body>
<div id="Container">
    <router-link to="/login?name=xiaoli&age=15" tag="span">登录</router-link>
    <router-link to="/register">注册</router-link>
    <transition mode="out-in">
        <router-view></router-view>
    </transition>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script src="./js/vue-router.js" type="text/javascript"></script>
<script>
 
    var login={
        template:'<h3>登录界面--{{$route.query.name}}--{{$route.query.age}}</h3>',
        created:function(){
            console.log(this.$route);   //获取路由信息,其中包括路由参数
        }
 
    };
    var register={
        template:'<h3>注册界面</h3>'
    };
 
    const routes = [
        { path: '/', redirect: '/login' },
        { path: '/login', component: login },
        { path: '/register', component: register }
    ];
 
 
    const router=new VueRouter({routes: routes});
 
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
        },
        router:router
    });
</script>

使用$route.param获得路由中定义参数

<head xmlns="http://www.w3.org/1999/html">
    <title>使用$route.param获得路由中定义参数</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style>
        /*设置当前router-link的样式*/
        .router-link-active{
            color:red;
            font-weight:bold;
        }
        .v-enter,.v-leave-to{
            opacity:0;
            transform:translateX(150px);
        }
        .v-enter-active,.v-leave-active{
            transition:all 1s ease;
        }
    </style>
</head>
<body>
<div id="Container">
    <router-link to="/login/2" tag="span">登录</router-link>
    <router-link to="/register">注册</router-link>
    <transition mode="out-in">
        <router-view></router-view>
    </transition>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script src="./js/vue-router.js" type="text/javascript"></script>
<script>
     /*通过$route.params获取参数*/
    var login={
        template:'<h3>登录界面--{{$route.params.id}}</h3>',
        created:function(){
            console.log(this.$route);   //获取路由信息,其中包括路由参数
        }
 
    };
    var register={
        template:'<h3>注册界面</h3>'
    };
 
    const routes = [
        { path: '/', redirect: '/login' },
        { path: '/login/:id', component: login },
        { path: '/register', component: register }
    ];
 
    const router=new VueRouter({routes: routes});
 
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
        },
        router:router
    });
</script>

路由循环嵌套

<body>
<div id="Container">
        <!--父路由视图占位符-->
        <router-view></router-view>
</div>
<template id="account">
    <div>
    账户页面
        <router-link to="/account/login">登录</router-link>
        <router-link to="/account/register">注册</router-link>
        <!--子路由视图占位符-->
        <router-view></router-view>
    </div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script src="./js/vue-router.js" type="text/javascript"></script>
<script>
    const account={
      template:'#account'
    };
 
    const routes = [
        {
            path: '/', redirect:'/account'
        },
        {
            path: '/account',
            component:account,
            children:[{    //children子路由配置  注意路径不要带斜线
                path: 'login',
                component:{
                    template:'<h3>登录组件页面</h3>'
                }
            },
                {
                    path: 'register',
                    component:{
                        template:'<h3>注册组件页面</h3>'
                    }
                }
            ]
        }
    ];
 
    const router=new VueRouter({routes: routes});
 
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
        },
        router:router
    });
</script>

使用命名视图实现经典布局

<head xmlns="http://www.w3.org/1999/html">
    <title>使用命名视图实现经典布局</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style>
        .container{
            display:flex;
            height:300px;
            padding:0;
        }
        h3{
            padding:0;
            margin:0;
        }
        .header{
            background-color: tomato;
        }
        .left{
            flex:2;
            background-color: pink;
        }
        .right{
            flex:8;
            background-color: darkgreen;
        }
    </style>
</head>
<body>
<div id="Container">
    <div>
    <router-view></router-view>
        <div class="container">
    <router-view name="left"></router-view>
    <router-view name="right"></router-view>
        </div>
    </div>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script src="./js/vue-router.js" type="text/javascript"></script>
<script>
    const header={
        template:'<h3 class="header">头部组件</h3>'
    };
 
    const leftBox={
        template:'<h3 class="left">左侧组件</h3>'
    };
 
    const rightBox={
        template:'<h3 class="right">右侧组件</h3>'
    };
 
    const routes = [
        {
            path: '/',
            components:{
                'default':header,    //默认组件
                'left':leftBox,      //自定义组件引用名字
                'right':rightBox
            }
        }
    ];
 
    const router=new VueRouter({routes: routes});
 
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
        },
        router:router
    });
</script>

名称案例 watch

<body>
<div id="Container">
<input type="text" v-model="firstName"/>+<input type="text" v-model="lastName"/>=<input type="text" v-model="fullName"/>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#Container',
        data: {
            firstName:'',
            lastName:'',
            fullName:''
        },
        methods: {
            change:function(){
                this.fullName=this.firstName+'-'+this.lastName
            }
        },
        watch:{ //监视data中的数据的变化
            /**
             * @param newVal新值
             * @param oldVal旧值
             */
            firstName:function(newVal,oldVal){
                this.change();
            },
            lastName:function(){
                this.change();
            }
        }
    });
</script>

watch监听路由的改变

<body>
<div id="Container">
    <!--父路由视图占位符-->
    <router-view></router-view>
</div>
<template id="account">
    <div>
        账户页面
        <router-link to="/account/login">登录</router-link>
        <router-link to="/account/register">注册</router-link>
        <!--子路由视图占位符-->
        <router-view></router-view>
    </div>
</template>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script src="./js/vue-router.js" type="text/javascript"></script>
<script>
    const account={
        template:'#account'
    };
    const routes = [
        {
            path: '/', redirect:'/account'
        },
        {
            path: '/account',
            component:account,
            children:[{    //children子路由配置  注意路径不要带斜线
                path: 'login',
                component:{
                    template:'<h3>登录组件页面</h3>'
                }
            },
                {
                    path: 'register',
                    component:{
                        template:'<h3>注册组件页面</h3>'
                    }
                }
            ]
        }
    ];
 
    const router=new VueRouter({routes: routes});
 
    new Vue({
        el: '#Container',
        data: {
        },
        methods: {
        },
        router:router,
        watch:{
            '$route.path':function(newVal,oldVal){
                console.log(newVal);   //当前路由
                console.log(oldVal);   //之前的路由
            }
        }
    });
</script>

名称案例 computed计算属性实现

<body>
<div id="Container">
    <input type="text" v-model="firstName"/>+<input type="text" v-model="lastName"/>=<input type="text" v-model="fullName"/>
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    new Vue({
        el: '#Container',
        data: {
            firstName:'',
            lastName:''
        },
        computed:{
            fullName:function(){  //内部的任何数据变化,都会重新执行   return(返回)一个值
                return this.firstName+'-'+this.lastName
            }
        }
    });
</script>

nrm 是一个 npm 源管理器,允许你快速地在 npm 源间切换。

 
$ npm install -g nrm   安装nrm
 
$ nrm ls  // 查看所有的支持源(有*号的表示当前所使用的源,以下[name]表示源的名称)
 
$ nrm use [name]  // 将npm下载源切换成指定的源
 
$ nrm help  // 查看nrm帮助
 
$ nrm home [name]  // 跳转到指定源的官网


参考:

https://www.cnblogs.com/joyho/articles/4430148.html

>npm install webpack@3 -g //安装webpack

webpack安装报错

C:\Users\Dell>npm install webpack@3.6 -g
npm ERR! code ETIMEDOUT
npm ERR! errno ETIMEDOUT
npm ERR! network request to https://registry.npmjs.org/webpack failed, reason: connect ETIMEDOUT 104.16.23.35:443
npm ERR! network This is a problem related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network 'proxy' config is set properly.  See: 'npm help config'
 
npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Dell\AppData\Roaming\npm-cache\_logs\2019-01-07T10_32_36_731Z-debug.log

解决方法,重新配置镜像源,可能宿舍网络太差:

npm config set registry https://registry.npm.taobao.org

重新安装,OK!

npm init
npm init 用来初始化生成一个新的 package.json 文件。它会向用户提问一系列问题,如果你觉得不用修改默认配置,一路回车就可以了。
如果使用了 -f(代表force)、-y(代表yes),则跳过提问阶段,直接生成一个新的 package.json 文件。
执行npm init -y命令,生成一个package.json文件,内容如下:

{
  "name": "webpackDemo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

执行 npm install jQuery -S 生成package-lock.json文件,内容如下:

{
  "name": "webpackDemo",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "jQuery": {
      "version": "1.7.4",
      "resolved": "http://registry.npm.taobao.org/jQuery/download/jQuery-1.7.4.tgz",
      "integrity": "sha1-8y3FyFpwRO6GS0RDue5F+UeLoTc="
    }
  }
}

并且生成一个node_modules文件夹。
webpack案例代码演示路径

index.html文件

<head>
<script src='./main.js' type="text/javascript"></script>
</head>
<body>
<div id="demo">这是一个简单的webpack demo</div>
</body>

main.js

import $ from 'jquery';
 
$(function(){
	alert($('#demo').text());
});

IE报错:SCRIPT1086: SCRIPT1086: Module import or export statement unexpected here,因为import是ES6的语法。
解决浏览器兼容es6方法

c:\webpackDemo>webpack ./codes/main.js ./dist/bundle.js
Hash: c08e1e23e12b03592706
Version: webpack 3.6.0
Time: 364ms
    Asset    Size  Chunks                    Chunk Names
bundle.js  275 kB       0  [emitted]  [big]  main
   [0] ./codes/main.js 73 bytes {0} [built]
    + 1 hidden module

index.html脚本引用修改为

<script src='../dist/bundle.js' type="text/javascript"></script>

引用OK!
webpack作用:
①webpack能处理js文件的依赖关系
②webpack能处理js文件的兼容问题,把不识别的高级语法,转为浏览器能识别的语法。
配置webpack.config.js

const path=require('path')
//通过node的模块,向外暴露了一个配置对象
module.exports={
	entry:path.join(__dirname,'./codes/main.js'),   //入口文件,标识,要打包的文件
	output:{
		path:path.join(__dirname,'./dist'),   //指定打包好的文件,输出到哪个目录中
		filename:'bundle.js'   //输出的文件的名称
	}
}

执行命令webpack

c:\webpackDemo>webpack
Hash: c08e1e23e12b03592706
Version: webpack 3.6.0
Time: 499ms
    Asset    Size  Chunks                    Chunk Names
bundle.js  275 kB       0  [emitted]  [big]  main
   [0] ./codes/main.js 73 bytes {0} [built]
    + 1 hidden module

webpack-dev-server(自动打包编译工具)
webpack-dev-server帮我们打包生成的js文件,并没有存放到实际的物理磁盘中,而是存放在内存中,所以项目中找不到js文件,可以通过根目录来进行访问。
npm常用安装执行命令都是什么意思?
npm install webpack-dev-server -D 安装webpack-dev-server:
npm install module_name -S    即    npm install module_name –save    写入dependencies
npm install module_name -D    即    npm install module_name –save-dev 写入devDependencies
npm install module_name -g 全局安装(命令行使用)
npm install module_name 本地安装(将安装包放在 ./node_modules 下)
devDependencies和dependencies区别
devDependencies(-D) 里面的插件只用于开发环境,不用于生产环境
dependencies(-S) 是需要发布到生产环境的
由于npm install webpack-dev-server -D是在本地安装的webpack-dev-server,所以无法把它当做脚本命令,在powershell终端中直接运行,只有安装到全局-g的工具,才能在终端正常指向。

为了保证webpack-dev-server正常执行,需要以下几个步骤:
①在package.json文件scripts属性中配置以下内容:
“dev”: “webpack-dev-server”
②npm install webpack@3.6.0 -D
③npm install webpack-cli@3.1.0 -D
④npm install webpack-dev-server@2.9.7 -D
注意在安装的过程中多次报如下错误:

c:\webpackDemo>npm run dev
 
> webpackDemo@1.0.0 dev c:\webpackDemo
> webpack-dev-server
 
c:\webpackDemo\node_modules\ajv-keywords\keywords\instanceof.js:52
    throw new Error('invalid "instanceof" keyword value ' + c);
    ^
 
Error: invalid "instanceof" keyword value Promise
    at getConstructor (c:\webpackDemo\node_modules\ajv-keywords\keywords\instanceof.js:52:11)
    at Ajv.compile (c:\webpackDemo\node_modules\ajv-keywords\keywords\instanceof.js:21:27)
    at Object.useCustomRule (c:\webpackDemo\node_modules\ajv\lib\compile\index.js:275:26)
    at Object.generate_custom [as code] (c:\webpackDemo\node_modules\ajv\lib\dotjs\custom.js:32:24)
    at Object.generate_validate [as validate] (c:\webpackDemo\node_modules\ajv\lib\dotjs\validate.js:347:35)
    at Object.generate_anyOf [as code] (c:\webpackDemo\node_modules\ajv\lib\dotjs\anyOf.js:34:27)
    at generate_validate (c:\webpackDemo\node_modules\ajv\lib\dotjs\validate.js:347:35)
    at localCompile (c:\webpackDemo\node_modules\ajv\lib\compile\index.js:87:22)
    at Ajv.compile (c:\webpackDemo\node_modules\ajv\lib\compile\index.js:56:13)
    at Ajv._compile (c:\webpackDemo\node_modules\ajv\lib\ajv.js:358:27)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! webpackDemo@1.0.0 dev: `webpack-dev-server`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the webpackDemo@1.0.0 dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
 
npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Dell\AppData\Roaming\npm-cache\_logs\2019-01-07T14_16_40_174Z-debug.log

于是调整webpack-dev-server版本达到了兼容

{
  "name": "webpackDemo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "jQuery": "^1.7.4",
    "jquery": "^3.3.1"
  },
  "devDependencies": {
    "webpack": "^3.6.0",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^2.9.7"
  }
}

运行npm run dev

c:\webpackDemo>npm run dev
 
> webpackDemo@1.0.0 dev c:\webpackDemo
> webpack-dev-server
 
Project is running at http://localhost:8080/
webpack output is served from /
Hash: 63e354da243eb5b105e8
Version: webpack 3.6.0
Time: 568ms
    Asset    Size  Chunks                    Chunk Names
bundle.js  597 kB       0  [emitted]  [big]  main
   [2] multi (webpack)-dev-server/client?http://localhost:8080 ./codes/main.js 40 bytes {0} [built]
   [3] (webpack)-dev-server/client?http://localhost:8080 7.95 kB {0} [built]
   [4] ./node_modules/url/url.js 23.3 kB {0} [built]
   [8] ./node_modules/querystring-es3/index.js 127 bytes {0} [built]
  [11] ./node_modules/strip-ansi/index.js 161 bytes {0} [built]
  [13] ./node_modules/loglevel/lib/loglevel.js 7.86 kB {0} [built]
  [14] (webpack)-dev-server/client/socket.js 1.05 kB {0} [built]
  [15] ./node_modules/sockjs-client/dist/sockjs.js 181 kB {0} [built]
  [16] (webpack)-dev-server/client/overlay.js 3.73 kB {0} [built]
  [17] ./node_modules/ansi-html/index.js 4.26 kB {0} [built]
  [18] ./node_modules/html-entities/index.js 231 bytes {0} [built]
  [21] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
  [23] (webpack)/hot/emitter.js 77 bytes {0} [built]
  [25] ./codes/main.js 73 bytes {0} [built]
  [26] ./node_modules/jquery/dist/jquery.js 272 kB {0} [built]
    + 12 hidden modules
webpack: Compiled successfully.

回车输入 http://localhost:8080/ 如下图:

由于webpack-dev-server编译的文件webpack output is served from /,而且存放在内存中,以便快速打包编译,所以index.html文件引入的时候,通过以下方式引入bundle.js:

<script src='/bundle.js' type="text/javascript"></script>

webpack-dev-server常用指令
修改package.json文件将dev属性修改为:”dev”: “webpack-dev-server –open –port 2000 –contentBase src –hot”,然后重启npm run dev,就可以打包后,根据设置的服务器端口/默认打开目录热重载,直接打开浏览器.
另一种使用webpack-dev-server指令的方式
在webpack.config.js中配置webpack-dev-server
首先在package.json中scripts配置: “dev”: “webpack-dev-server”,然后再webpack.config.js中配置如下:

const path=require('path')
const webpack=require('webpack')
 
//通过node的模块,向外暴露了一个配置对象
module.exports={
	entry:path.join(__dirname,'./src/main.js'),   //入口文件,标识,要打包的文件
	output:{
		path:path.join(__dirname,'./dist'),   //指定打包好的文件,输出到哪个目录中
		filename:'bundle.js'   //输出的文件的名称
	},
	devServer:{
		open:true,
		port:3000,
		contentBase:'src',
		hot:true
	},
	plugins:[    //配置插件的节点  
	new webpack.HotModuleReplacementPlugin()
	]
}

html-webpack-plugin插件的使用
html-webpack-plugin 插件是用于编译 Webpack 项目中的 html 类型的文件,如果直接将 html 文件置于 ./src 目录中,用 Webpack 打包时是不会编译到生产环境中的。因为 Webpack 编译任何文件都需要基于配置文件先行配置的。
html-webpack-plugin安装:npm install html-webpack-plugin -D

const path=require('path')
const webpack=require('webpack')
//内存中生成html的插件
//只要是插件都一定要放到插件节点中去
const htmlWebpackPlugin=require('html-webpack-plugin')
 
module.exports={
	entry:path.join(__dirname,'./src/main.js'),   //入口文件,标识,要打包的文件
	output:{
		path:path.join(__dirname,'./dist'),   //指定打包好的文件,输出到哪个目录中
		filename:'bundle.js'   //输出的文件的名称
	},
	devServer:{
		open:true,
		port:3000,
		contentBase:'src',
		hot:true
	},
	plugins:[    //配置插件的节点  
	new webpack.HotModuleReplacementPlugin(),
	new htmlWebpackPlugin({
		template:path.join(__dirname,'./src/index.html'),  //指定模板页面,将来会根据指定的页面在内存中生成页面
		filename:'index123.html'     //指定生成的页面名称
	})
	]
}

你就可以通过http://localhost:3000/index123.html访问/src/index.html模板文件
index.html文件代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<!-- <script src='/bundle.js' type='text/javascript'></script> -->
	</head>
	<body>
		<div id="demo">这是一个webpack的demo啊</div>
	</body>
</html>

index123.html源码文件:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<!-- <script src='/bundle.js' type='text/javascript'></script> -->
	</head>
	<body>
		<div id="demo">这是一个webpack的demo啊</div>
        <!--自动挂载内存中的js文件,因为在web.config.js文件中module.exports配置关联起来的-->
	<script type="text/javascript" src="bundle.js"></script></body>
</html>

webpack只能打包js文件,处理非js类型文件需要安装一些文件类型对应的第三方loader加载器
①安装cssloader加载器 npm install style-loader css-loader -D
②定义/src/css/main.css文件

#demo{
	background-color: red;
	width:250px;
	height:250px;
}

③/src/main.js引入main.css内容

import $ from 'jquery'
import './css/main.css'
 
$(function(){
	alert($('#demo').text()+'d2222dd');
})

④配置webpack.config.js文件中的module属性

const path=require('path')
const webpack=require('webpack')
//内存中生成html的插件
//只要是插件都一定要放到插件节点中去
const htmlWebpackPlugin=require('html-webpack-plugin')
 
module.exports={
	entry:path.join(__dirname,'./src/main.js'),   //入口文件,标识,要打包的文件
	output:{
		path:path.join(__dirname,'./dist'),   //指定打包好的文件,输出到哪个目录中
		filename:'bundle.js'   //输出的文件的名称
	},
	devServer:{
		open:true,
		port:3000,
		contentBase:'src',
		hot:true
	},
	plugins:[    //配置插件的节点  
	new webpack.HotModuleReplacementPlugin(),
	new htmlWebpackPlugin({
		template:path.join(__dirname,'./src/index.html'),  //指定模板页面,将来会根据指定的页面在内存中生成页面
		filename:'index123.html'     //指定生成的页面名称
	})
	],
	module:{  //配置所有第三方模块加载器
	rules:[	//所有第三方模块的匹配规则,如下匹配所有以css文件结尾的文件,使用style-loader和css-loader模块加载器,多个loader从右到左依次调用
		{test: /\.css$/,use:['style-loader','css-loader']}     
	]}
}

这样就可以正常解析css文件,进行编译了.
更多第三方loader参考

https://webpack.js.org/loaders/

css样式采用外部资源(字体库和图片之类的url地址)时,比如background-image: url(‘../images/zs.jpeg’);报错提示如下:
Module parse failed: C:\Users\Administrator\app\src\images\zs.jpeg Unexpected character ‘�’ (1:0)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
我们需要安装第三方loader
npm install url-loader file-loader -D
module添加图片的rule规则,如下:
module:{ //配置所有第三方模块加载器
rules:[ //所有第三方模块的匹配规则,如下匹配所有以css文件结尾的文件,使用style-loader和css-loader模块加载器
{test: /\.css$/,use:[‘style-loader’,’css-loader’]},
{test:/\.(jpg|jpeg|png|gif|bmp)$/,use:’url-loader’}
]}
默认不限制图片的大小,对图片进行base64编码,解析如下:

background-image: url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwME…T3BnpHwmybZLioi6+IVb4dgu66iqqGhbUPEsN3g5KLpJXjaQ7KQ5jZHuc4XJJyjgillbTP/9k=);

当前图片大小为112,601 字节,对编码大小进行限制如下:

{test:/\.(jpg|jpeg|png|gif|bmp)$/,use:'url-loader?limit=112600'}

解析如下:

background-image: url(4a2ffe908d473eb7c4ae366eac5c3af6.jpeg);

所以,如果图片大于或者等于limit设定值,则不会被转为base64编码,如果做如下配置

{test:/\.(jpg|jpeg|png|gif|bmp)$/,use:'url-loader?limit=112600&name=[hash:32]-[name].[ext]'}

不转base64编码生成的图片路径:

url(4a2ffe908d473eb7c4ae366eac5c3af6-zs.jpeg)

在webpack中只能处理一部分ES6的新语法,无法打包的ES6和ES7语法,需要借助第三方loader实现,当第三方loader把高级语法处理完之后,会把结果交给webpack去打包,Babel就是这样产生了。

在webpack中,我们可以运行如下两套命令,安装两套包,安装Babel相关的loader功能:
①npm install babel-core babel-loader babel-plugin-transfrom-runtime -D
②npm install babel-preset-env babel-preset-stage-0 -D

Render函数是Vue2.x版本新增的一个函数;使用虚拟dom来渲染节点提升性能,因为它是基于JavaScript计算。通过使用createElement(h)来创建dom节点。createElement是render的核心方法。其Vue编译的时候会把template里面的节点解析成虚拟dom;
什么是虚拟dom?虚拟dom不同于真正的dom,它是一个JavaScript对象。当状态发生变化的时候虚拟dom会进行一个diff判断/运算;然后判断哪些dom是需要被替换的而不是全部重绘,所以性能会比dom操作高很多。

<body>
<div id="Container">
</div>
</body>
<script src="./js/vue.js" type="text/javascript"></script>
<script>
    var login={template:'<h3>这是一个登陆组件</h3>'};
    new Vue({
        el: '#Container',
        data: {
            firstName:'',
            lastName:''
        },
        render:function(createElement){
            return createElement(login);
        }
    });
</script>

webpack中使用vue
安装vue模块
npm install vue -S

在webpack中,使用 import Vue from ‘vue’导入的vue构造函数,功能不完善,只提供了runtime-only的方式,并没有提供像网页中那样使用的方式。
包的查找规则:
1.项目根目录中有没有node_modules的文件夹
2.在node_modules中根据包名,找对应的文件夹
3.在文件夹中,找一个叫做package.json的包配置文件
4.在package.json文件中,查找一个main属性

vue下package.json的main属性,配置如下:
dist/vue.runtime.common.js

有以下两种方式在webpack中,使用Vue:
方法一:vue下package.json中修改”main”: “dist/vue.runtime.common.js”为”main”: “dist/vue.common.js” (不推荐)
方法二:import Vue from ‘../node_modules/vue/dist/vue.js’; (node_modules/vue/dist/vue.js等效)
方法三:依旧通过import Vue from ‘vue’;导入,但是需要在webpack.config.js中做一些配置,module.exports对象中添加如下键值对,修改vue导入包的路径:

	resolve:{
		alias:{
			"vue$":'vue/dist/vue.js'
		}
	}

vue runtime-only模式 渲染组件到容器中
①安装vue所需要loader
默认,webpack无法打包.vue文件,需要安装相关的loader
npm install vue-loader@14 vue-template-compiler -D

②创建.vue文件:
采用传统的方式(如下),使用组件(components属性定义),组件由三部分组成无法打包vue组件,需要使用render方式

<template>
	<div>
		<div>登录组件</div>
	</div>
</template>
 
<script>
	export default {
		data() {
			return {
 
			};
		}
	}
</script>
 
<style>
</style>

创建/src/components/login.vue文件

<template>
		<div>登录组件</div>
</template>

③然后在main.js文件中导入模块和组件,代码如下:

import Vue from 'vue'
 
import login from './components/login.vue'
 
new Vue({
	'el':'#container',
	data:{
		msg:'组件的使用'    
	},
 	render:function(createElement){     //采用传统的方式,使用组件(components属性定义),无法打包vue组件,需要使用render方式
		return createElement(login);
	} 
});

简写模式,效果同上:

import Vue from 'vue'
import login from './components/login.vue'
new Vue({
	'el':'#container',
	data:{
		msg:'组件的使用'
	},
 	render:c => c(login)
});

④package.json文件中配置模块rule规则:

{test:/\.vue$/,use:'vue-loader'}

在node中,使用var 名称=require(‘模块标识符’)
module.exports和exports向外暴露成员

export default和export的区别
ES6导入模块:import 模块名称 from ‘模块标识符’ || import ‘路径’
ES6导出模块:使用export default 和 export向外暴露成员
使用注意事项:
export default向外暴露的成员,可以使用任意变量来接收成员.使用export导出的成员,必须按照严格方式相同的名称接收(可以自定义起别名).
export default在一个模块中只允许向外暴露一次,export可以向外多次暴露
在一个模块中可以同时使用export default 和 export向外暴露成员
使用export向外暴露的成员,只能使用{}的形式来接收,这种形式叫做按需导出
正是因为export default命令其实只是输出一个叫做default的变量,所以它后面不能跟变量声明语句,而export需要跟变量声明或者大括号作为输出
test.js文件 导出模块

export default{
	name:'小明',
	age:20
}
 
/* 无效方式,报错
var xiaoli='xiaoli';
export xiaoli; */
export var xiaoli='xiaoli';
export var xiaobaiInfo={name:'小白',age:30};

main.js文件 导入模块

import xiaomingInfo,{xiaoli as xiaoliInfo,xiaoli,xiaobaiInfo} from './js/test.js'
console.log(xiaomingInfo);    //输出 {name: "小明", age: 20}
console.log(xiaoliInfo);      //变量起别名 输出 xiaoli
console.log(xiaoli);          //输出  xiaoli
console.log(xiaobaiInfo);   //输出 {name: "小白", age: 30}

结合webpack使用vue-router
index.html

	<div id="container">
	</div>

main.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import app from './components/app.vue'
import login from './components/login.vue'
import register from './components/register.vue'
Vue.use(VueRouter)
    const routes = [
        { path: '/login', component: login },
        { path: '/register', component: register }
    ];
		const router=new VueRouter({routes: routes});
	new Vue({
		el:'#container',
		data:{
 
		},
		render:function(createElement){
			return createElement(app);
		},
		router:router
	})

app.vue

<template>
	<div>
		<div>个人中心</div>
		<router-link to='./login'>登录</router-link>
		<router-link to='./register'>注册</router-link>
		<router-view></router-view>
		</div>
</template>
<script>
	export default {
		data() {
			return {	
			};
		}
	}
</script>
<style>
</style>

login.vue

<template>
	<div>
		<div>登录组件</div>
	</div>
</template>
<script>
	export default {
		data() {
			return {
				msg:'这是一个消息'
			};
		},
		methods:{
 
		}
	}
</script>
<style>
</style>

register.vue

<template>
<div>
	注册组件
</div>
</template>
<script>
	export default {
		data() {
			return {	
			};
		}
	}
</script>
<style>
</style>

webpack中实现children子路由
index.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
	<div id="container">
 
	</div>
	</body>
</html>

main.js

import Vue from 'vue'
 
import VueRouter from 'vue-router'
 
import app from './components/app.vue'
 
import account from './components/account.vue'
 
import login from './components/login.vue'
 
import register from './components/register.vue'
 
Vue.use(VueRouter)
 
const routes = [{
	path: '/account',
	component: account,
	children: [{
			path: 'login',
			component: login,
		},
		{
			path: 'register',
			component: register,
		}
	]
}];
 
const router = new VueRouter({
	routes: routes
});
 
new Vue({
	el: '#container',
	data: {
	},
	render: function(createElement) {
		return createElement(app);
	},
	router: router
})

app.vue

<template>
	<div>
		<div>个人中心</div>
          <router-link to='/account'>账户</router-link>
		  <router-view></router-view>
		</div>
</template>
<script>
	export default {
		data() {
			return {
			};
		}
	}
</script>
<style>
</style>

父组件 account.vue

<template>
	<div>
		<router-link to='/account/login'>登录</router-link>
		<router-link to='/account/register'>注册</router-link>
		<router-view></router-view>
	</div>
</template>
<script>
	export default {
		data() {
			return {
			};
		}
	}
</script>
<style>
</style>

子组件 register.vue

<template>
<div>
	注册组件
</div>
</template>
<script>
	export default {
		data() {
			return {
			};
		}
	}
</script>
<style>
</style>

子组件 login.vue

<template>
	<div>
		<div>登录组件</div>
	</div>
</template>
<script>
	export default {
		data() {
			return {
				msg:'这是一个消息'
			};
		},
		methods:{
 
		}
	}
</script>
<style>
</style>

scoped 在style标签上添加scoped属性,以表示它的样式作用于当下的模块,很好的实现了样式私有化的目的,这是一个非常好的机制。但是为什么要慎用呢?在实际业务中我们往往会对公共组件样式做细微的调整,如果添加了scoped属性,那么样式将会变得不易修改。

<style scoped>
	div{
		color:red;
	}
</style>

默认只支持普通样式,设置lang属性支持scss,sass样式

<style scoped lang="scss">
	body{
		div{
			color:red;
		}
	}
</style>

117 118跳过
Mint-ui的使用(Mint UI 基于 Vue.js 的移动端组件库)

文档地址

https://mint-ui.github.io/#!/zh-cn

安装 npm i mint-ui -S
代码实例
main.js

import Vue from 'vue'
import MintUI from 'mint-ui'
import 'mint-ui/lib/style.css'
import App from './App.vue'
Vue.use(MintUI)
new Vue({
  el: '#app',
  data:{
	  msg:'模板消息'
  },
  render:function(createElement){
		return createElement(App)
	}
})

CSS Components的使用示例(在App.vue中,通过以上引用可以直接使用):

<template>
	<div>
		<mt-button type="default" @click.native="show">点击按钮触发</mt-button>
	</div>
</template>

JS Components的使用示例(App.vue):

<template>
	<div>
		<mt-button type="default" @click.native="show">点击按钮触发</mt-button>
	</div>
</template>
 
<script>
	import { Toast } from 'mint-ui';
	export default {
		data() {
			return {
			}
		},
		methods:{
			show(){
				console.log('sdfjksdf');
				Toast('提示信息');
			}
		}
	}
</script>
 
<style>

JS Components Toast组件,如果未引用会报如下错误:

Uncaught ReferenceError: Toast is not defined
    at VueComponent.show

Mint UI按需导入
npm install babel-plugin-component -D
win10下安装babel-plugin-component有个坑,默认创建或者修改文件必须包含名称(键名),也就是不能以.**命名文件,所以无法创建.babelrc,解决方案如下:
新建1.babelrc文件,然后重命名rename 1.babelrc .babelrc,然后配置如下:

{
  "presets": [
    ["es2015", { "modules": false }]
  ],
  "plugins": [["component", [
    {
      "libraryName": "mint-ui",
      "style": true
    }
  ]]]
}

main.js

import Vue from 'vue'
import 'mint-ui/lib/style.css'
import { Button } from 'mint-ui'
import App from './App.vue'
 
Vue.component(Button.name, Button)
new Vue({
  el: '#app',
  data:{
	  msg:'模板消息'
  },
	render:c=>c(App)
})

App.vue

<template>
	<div>
      <mt-button type="danger">danger</mt-button>
	</div>
</template>

Vue中mui的使用
main.js引入css文件

import Vue from 'vue'
import app from './components/app.vue'
import './lib/mui/css/mui.min.css'
new Vue({
	el: '#container',
	data: {
	},
	render: function(createElement) {
		return createElement(app);
	}
})

在组件中使用app.vue中使用:

<template>
	<div>
<span class="mui-badge">1</span>
<span class="mui-badge mui-badge-primary">12</span>
<span class="mui-badge mui-badge-success">123</span>
<span class="mui-badge mui-badge-warning">3</span>
<span class="mui-badge mui-badge-danger">45</span>
<span class="mui-badge mui-badge-purple">456</span>
	</div>
</template>

在加载mui css文件ttf文件时,出现以下错误:

./src/lib/mui/fonts/mui.ttf
Module parse failed: C:\Users\Administrator\app\src\lib\mui\fonts\mui.ttf 
Unexpected character '

在webpack.config.js文件中的module属性中,配置如下模块解析规则,即可解决:

{test:/\.(jpg|jpeg|png|gif|bmp|eot|ttf|svg)$/,use:'url-loader?limit=112600&name=[hash:32]-[name].[ext]'}

HBuilder X中同步代码到码云
在工具=>插件安装=>git插件,点击安装即可安装HBuilder X 的插件git

.gitignore文件设置
node_modules
.idea
.git

首先在码云新建仓库,新建仓库后,Git全局设置:

git config --global user.name "lansesuixiang"
git config --global user.email "412198579@qq.com"

新建本地仓库
git init

添加远程库
git remote add origin https://gitee.com/lansesuixiang/vuedemo.git

git status
查询文件的状态

git add .
提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件(提交到本地的版本库)
git commit -m “init my project” 报错如下:

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'Administrator@CN-20170415JVTT.(
none)')

执行以下两条命令即可解决解决

                                     
git config --global user.name "lansesuixiang"                                           
git config --global user.email "412198579@qq.com"

如何退出git bash vim编辑器:

 
ESC  --》 退出编辑状态;接着 连续按两次大写字母键 Z,接着你会惊喜的发现,终于保存好退出来了!

在git bash中执行ssh-keygen -t rsa -C “412198579@qq.com”生成SSH公钥复制到码云中

 
Administrator@CN-20170415JVTT MINGW32 ~
$ ssh-keygen -t rsa -C "412198579@qq.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/c/Users/Administrator/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /c/Users/Administrator/.ssh/id_rsa.
Your public key has been saved in /c/Users/Administrator/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:wADt+pPL+kjhcvVxmsSczd97uAiwdMt2VwyWO0xe6Fg 412198579@qq.com
The key's randomart image is:
+---[RSA 2048]----+
|  .o.            |
|    .o       o   |
|   .  o     E .  |
|    .o =   O =   |
|  ... O S . * o  |
| ..o + X o . o   |
|. +. .= = o o.   |
| + o+  . o o...  |
|  oo+o    . oo   |
+----[SHA256]-----+

git push -u origin master 上面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了

HBuilder X中同步代码到码云

git修改文件后,git提交
①命令行传统方式
git add .
git commit -m “something”
git push
②HBuilder X中修改提交
选中项目 先git commit 后git push
mui自定义图标的使用
①import ‘./lib/mui/css/icons-extra.css’
②将mui-icons-extra.ttf复制到项目中
③根据demo中的样式使用即可

Promise对象解决回调地狱问题
Promise 对象是 JavaScript 的异步操作解决方案,为异步操作提供统一接口。它起到代理作用(proxy),充当异步操作与回调函数之间的中介,使得异步操作具备同步操作的接口。Promise 可以让异步操作写起来,就像在写同步操作的流程,而不必一层层地嵌套回调函数。
Promise 的设计思想是,所有异步任务都返回一个 Promise 实例。Promise 实例有一个then方法,用来指定下一步的回调函数。
回调地狱
首先创建1.txt 2.txt 3.txt
demo.js 文件内容 读取单个文件内容

const fs=require('fs')
const path=require('path')
function getFileInfo(filePath,callback){
	fs.readFile(path.join(__dirname,filePath),'utf-8',(err,datastr)=>{  //回调异步方法
		if(err){
			return callback(err) 
		}
		callback(null,datastr)
	})
}
 
getFileInfo('1.txt',(err,datastr)=>{
	if(err){
		console.log(err)
	}else{
		console.log(datastr)
	}
})

按顺序读取1.txt 2.txt 3.txt内容

const fs = require('fs')
const path = require('path')
 
function getFileInfo(filePath, sucCallback, errCallback) {
	fs.readFile(path.join(__dirname, filePath), 'utf-8', (err, datastr) => { //回调异步方法
		if (err) {
			return errCallback(err)
		}
		sucCallback(datastr)
	})
}
 
//回调地狱案例  层层嵌套
//按顺序读取1.txt 2.txt 3.txt   
getFileInfo('1.txt', function(data){
	console.log(data);
	getFileInfo('2.txt', function(data){
		console.log(data);
		getFileInfo('3.txt', function(data){
			console.log(data);
		})
	})
})

单个promise demo

//promise
const fs = require('fs')
const path = require('path')
 
// new出来Promise实例,只是代表形式上的异步操作,我们只知道它是一个异步操作,但是做什么事情,我们还不清楚
// var promise = new Promise();
 
//这是一个具体的异步操作,其中function指定了一个具体的异步操作
//每当new Promise就会执行一个异步操作,而且返回一个Promise实例
 
/* function getFileInfo(filePath) {
	var promise = new Promise(
		function() {
			fs.readFile(filePath, 'utf-8', function(err, data) {
				if (err) return console.log('发生了错误' + err);
				console.log('读取的数据:' + data);
			});
		});
}
 
getFileInfo(path.join(__dirname, '3.txt'));
 */
 
function getFileInfo(filePath) {
	var promise = new Promise(
		function(resolve,reject) {  //形参 参数为成功和失败的回调函数
			//异步操作
			fs.readFile(filePath, 'utf-8', function(err, data) {
				if (err) return reject(err);   //失败回调
				resolve(data);  //成功回调
			});
		});
		return promise;
}
 
var p=getFileInfo(path.join(__dirname, '5.txt'));
// .then定义 Promise 的成功和失败情况的回调函数。
p.then(function(data){
	console.log('执行成功'+data);
},function(err){
	console.log('执行失败'+err.message);
})

promise正确姿势 按顺序读取1.txt 2.txt 3.txt

const fs = require('fs')
const path = require('path')
 
function getFileInfo(filePath) {
	var promise = new Promise(
		function(resolve, reject) { //形参 参数为成功和失败的回调函数
			//异步操作
			fs.readFile(filePath, 'utf-8', function(err, data) {
				if (err) return reject(err); //失败回调
				resolve(data); //成功回调
			});
		});
	return promise;
}
 
var p = getFileInfo(path.join(__dirname, '1.txt'));
p.then(function(data) {
	console.log('执行成功1--' + data);
	return getFileInfo(path.join(__dirname, '2.txt'))
}).then(function(data) {
	console.log('执行成功2--' + data);
	return getFileInfo(path.join(__dirname, '4.txt'))
}).then(function(data){
	console.log('执行成功3--'+data);
},function(err){
	console.log('执行失败'+err)
})

以上demo,无法正确执行错误回调,下边正确修改

const fs = require('fs')
const path = require('path')
 
function getFileInfo(filePath) {
	var promise = new Promise(
		function(resolve, reject) { //形参 参数为成功和失败的回调函数
			//异步操作
			fs.readFile(filePath, 'utf-8', function(err, data) {
				if (err) return reject(err); //失败回调
				resolve(data); //成功回调
			});
		});
	return promise;
}
 
var p = getFileInfo(path.join(__dirname, '1.txt'));
p.then(function(data) {
	console.log('执行成功1--' + data);
	return getFileInfo(path.join(__dirname, '1.txt'))
},function(err){
	console.log('执行失败1--' + err);
	return getFileInfo(path.join(__dirname, '2.txt'))
}).then(function(data) {
	console.log('执行成功2--' + data);
	return getFileInfo(path.join(__dirname, '2.txt'))
},function(err){
	console.log('执行失败2--' + err);
	return getFileInfo(path.join(__dirname, '3.txt'))
}).then(function(data){
	console.log('执行成功3--'+data);
},function(err){
	console.log('执行失败'+err)
})

捕获错误,停止继续执行

const fs = require('fs')
const path = require('path')
 
function getFileInfo(filePath) {
 
	var p = new Promise(function(resolve, reject) {
			fs.readFile(filePath,'utf-8',function(err, data) {
					if (err) return reject(err);
					resolve(data);
				}
			);
	});
	return p;
}
 
	var p = getFileInfo(path.join(__dirname, '1.txt'));
	p.then(function(data){
		console.log(data);
		return getFileInfo(path.join(__dirname, '22.txt'));
	})
	.then(function(data){
		console.log(data);
		return getFileInfo(path.join(__dirname, '3.txt'));
 
	})
	.then(function(data){
		console.log('ok');
		console.log(data)
	})
	.catch(function(err){
		console.log('发生错误'+err.message+'停止继续执行')
	})

jquery中ajax使用promise指定回调成功回调函数

var jsdom = require("jsdom"); 
var $ = require("jquery")(jsdom.jsdom().defaultView);
 
$(function(){
	$.ajax({
	url:'http://www.liulongbin.top:3005/api/getlunbo',
	async:false,
	dataType:'json'
	}).then(function(response){  //这样就可以将data数据继续传递至调用该方法接下去执行的then()方法的回调函数中了。
		console.log(JSON.stringify(response))
	});
});

坑:在node中服务器端使用jquery遇到jQuery requires a window with a document,原因在于jquery的运行需要window的运行环境,在浏览器端是没问题的,而在服务器上就不包含了,需要jsdom创建一个window给它,就可以解决这个问题.

babel-plugin-transform-remove-strict-mode
使用babel进行es6转es5时,默认转化之后是严格模式,有些时候我们想去除严格模式就需要babel-plugin-transform-remove-strict-mode这个东西了。

https://www.npmjs.com/package/babel-plugin-transform-remove-strict-mode

制作顶部滑动条的坑:
需要借助于 MUI 中的 tab-top-webview-main.html
需要把 slider 区域的 mui-fullscreen 类去掉
滑动条无法正常触发滑动,通过检查官方文档,发现这是JS组件,需要被初始化一下:
导入 mui.js
调用官方提供的 方式 去初始化:
mui(‘.mui-scroll-wrapper’).scroll({
deceleration: 0.0005 //flick 减速系数,系数越大,滚动速度越慢,滚动距离越小,默认值0.0006
});
我们在初始化 滑动条 的时候,导入的 mui.js ,但是,控制台报错: Uncaught TypeError: ‘caller’, ‘callee’, and ‘arguments’ properties may not be accessed on strict mode
经过我们合理的推测,觉得,可能是 mui.js 中用到了 ‘caller’, ‘callee’, and ‘arguments’ 东西,但是, webpack 打包好的 bundle.js 中,默认是启用严格模式的,所以,这两者冲突了;
解决方案: 1. 把 mui.js 中的 非严格 模式的代码改掉;但是不现实; 2. 把 webpack 打包时候的严格模式禁用掉;
最终,我们选择了 plan B 移除严格模式: 使用这个插件 babel-plugin-transform-remove-strict-mode
刚进入 图片分享页面的时候, 滑动条无法正常工作, 经过我们认真的分析,发现, 如果要初始化 滑动条,必须要等 DOM 元素加载完毕,所以,我们把 初始化 滑动条 的代码,搬到了 mounted 生命周期函数中;
当 滑动条 调试OK后,发现, tabbar 无法正常工作了,这时候,我们需要把 每个 tabbar 按钮的 样式中 mui-tab-item 重新改一下名字;
获取所有分类,并渲染 分类列表;

webpack兼容性

{
  "name": "meetwebpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "vue": "^2.6.12"
  },
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-preset-es2015": "^6.24.1",
    "css-loader": "^3.0.0",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "less": "^3.13.0",
    "less-loader": "^4.1.0",
    "style-loader": "^2.0.0",
    "uglifyjs-webpack-plugin": "^1.1.1",
    "url-loader": "^2.1.0",
    "vue-loader": "^13.0.0",
    "vue-template-compiler": "^2.6.12",
    "webpack": "^3.6.0"
  }
}

参考:https://blog.csdn.net/qq_44815747/article/details/

全局安装webpack(这里我们指定版本号为3.6.0,因为vue cli2依赖这个版本)
npm install webpack@3.6.0 -g

为什么全局安装后,还需要局部安装呢?
在终端执行webpack命令,使用的全局安装的webpack
当在package.json中定义了scripts时,其中包含了webpack命令,那么使用的是局部webpack

webpack ./src/main.js ./dist/bundle.js

npm init 生成 package.json文件

npm install webpack@3.6.0 –save-dev

package.json增加如下依赖
  "devDependencies": {
    "webpack": "^3.6.0"
  }

我们主要是用webpack来处理我们写的js代码,并且webpack之间会自动处理js之间相关的依赖,但是,在开发中我们不仅有基本的js代码处理,我们也需要加在css、图片,也包括一些高级的将ES6转成ES5代码,将typescript转换成ES5代码,将scss、less转成css,将.jsx、.vue文件转换成js文件等等。

对于webpack本身的能力来说,这些转换是不支持的,那怎么办呢?给webpack扩展对应的loader就可以了。大部分loader我们都可以在webpack官网找到,并且学习使用方法。

loader使用过程:
步骤一:通过npm安装loader
步骤二:在webpack.config.js中的modules关键字下进行配置

css-loader 解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码
npm install css-loader –save-dev

style-loader 将模块的导出作为样式添加到 DOM 中
npm install style-loader –save-dev

npm install file-loader@1.1.5 –save-dev

npm install –save-dev babel-loader@7.1.5 babel-core@6.26.3 babel-preset-es2015@6.24.1 webpack

npm install vue@2.6.12 –save

bundle.js:1328 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

(found in )

runtime-only 代码中不可以有任何template
runtime-compiler 代码中,可以有template,因为有compiler可以用于编译template

import Vue from 'vue'
new Vue({
    el: "#app",
    template: `
    <div>
    <h2>{{message}}</h2>
    <button @click="btnClick">按钮</button>
    </div>`,
    data: {
        message: "我是中国人"
    },
    methods: {
        btnClick() {
            alert('btnClick')
        }
    }
})
 
const App = {
    template: `
    <div>
    <h2>{{message}}</h2>
    <button @click="btnClick">按钮</button>
    </div>`,
    methods: {
        btnClick() {
            alert('btnClick')
        }
    },
    data() {
        return { message: "我是中国人" }
    }
}
 
import Vue from 'vue'
new Vue({
    el: "#app",
    template: '<App/>',
    components: {
        App
    }
})

npm install –save-dev vue-loader@15.4.2 vue-template-compiler@2.5.21

ERROR in ./src/vue/App.vue
vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.

npm install –save-dev html-webpack-plugin@2.30.1

npm install –save-dev uglifyjs-webpack-plugin@1.1.1

npm install webpack-dev-server@2.9.0 –save-dev

npm install webpack-merge –save-dev

脚手架

npm install -g @vue/cli
 
拉取 2.x 模板 (旧版本)
npm install -g @vue/cli-init
 
脚手架2.x创建项目
vue init webpack my-project

runtime-compiler
template -> ast -> render -> vdom -> UI
如果在之后的开发中,你依然使用template,就需要选择Runtime-Compiler

runtimeonly(性能更高代码量更少)
render -> vdom -> UI
如果你之后的开发中,使用的是.vue文件夹开发,那么可以选择Runtime-only

vue-router.esm.js?fe87:2065 Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: “/profile”.

Vue.use(Router)
// Avoided redundant navigation to current location 避免重复点击一个路由

const originalReplace = Router.prototype.replace;
Router.prototype.replace = function replace(location) {
  return originalReplace.call(this, location).catch(err => err);
};

npm install postcss-px-to-viewport –save-deve

postcss.config.js

vue.runtime.esm.js?2b0e:619 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “currentIndex”