vue中常用的指令
v-model
双向数据绑定,一般用于表单元素
v-for
对数组或对象进行循环操作,使用的是v-for
<!-- 普通循环 -->
<li v-for="value in arr">{{value}}</li>
<!-- 键值循环 -->
<li v-for="(v,k) in arr">{{k}}={{v}}</li>
<!-- 可以直接循环包含重复数据的集合,可以通过指定:key属性绑定唯一key,当更新元素时可重用元素,提高效率 ,变化的替换,不变的不替换
官方解释:当 Vue.js 用 v-for
正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在 特定索引下显示已被渲染过的每个元素。
-->
<li v-for="(v,k) in arr2" :key="k">{{v}}</li>
<li v-for="(user,index) in users">
{{index+1}},{{user.id}},{{user.name}},{{user.age}}
</li>
v-on
用来绑定事件,用法:v-on:事件="函数" v-on:click="" 简写方式 @click="" vue方法里的this表示当前vue实例 vue方法访问vue方法或数据都要用this,不能直接访问
v-show/v-if
用来显示或隐藏元素,v-show是通过display实现,v-if是每次删除后再重新创建
指令能直接访问vue实例中的数据
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <script src="js/vue.js"></script> <link rel="stylesheet" href=""> </head> <body> <div id="app"> <button @click="flag=!flag">显示或隐藏</button> <div style=" 100px;height: 100px;background: red;" v-if="flag"></div> </div> <script type="text/javascript"> window.onload=function(){ new Vue({ el:"#app", data:{ flag:false } }); } </script> </body> </html>
用户管理例子
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <link rel="stylesheet" href=""> <script src="js/vue.js"></script> <link rel="stylesheet" href="bootstrap/bootstrap.min.css"> <script src="bootstrap/jquery.min.js"></script> <script src="bootstrap/bootstrap.min.js"></script> </head> <body> <div class="container"> <h2 class="text-center">添加用户</h2> <form class="form-horizontal"> <div class="form-group"> <label for="userName" class="control-label col-lg-2 col-md-offset-2">姓名:</label> <div class="col-md-6"> <input type="text" id="userName" class="form-control" v-model="user.name" placeholder="请输入姓名"></input> </div> </div> <div class="form-group"> <label for="userAge" class="control-label col-lg-2 col-md-offset-2">年龄:</label> <div class="col-md-6"> <input type="text" id="userAge" class="form-control" v-model="user.age" placeholder="请输入年龄"></input> </div> </div> <div class="form-group"> <label for="userEmail" class="control-label col-lg-2 col-md-offset-2">邮箱:</label> <div class="col-md-6"> <input type="text" id="userEmail" class="form-control" v-model="user.email" placeholder="请输入邮箱"></input> </div> </div> <div class="form-group text-center"> <input type="button" value="添加" class="btn btn-primary" @click="addUser"> <input type="reset" value="重置" class="btn btn-primary"> </div> </form><!-- form-horizontal --> <hr> <table class="table table-bordered table-hover" > <caption class="h3 text-center text-info"> 用户列表</caption> <thead> <tr > <th class="text-center">序号</th> <th class="text-center">姓名</th> <th class="text-center">年龄</th> <th class="text-center">邮箱</th> <th class="text-center">操作</th> </tr> </thead> <tbody> <tr v-for="(user,index) in users" class="text-center"> <td >{{index+1}} </td> <td >{{user.name}} </td> <td >{{user.age}} </td> <td >{{user.email}} </td> <td > <button class="btn btn-danger btn-sm" data-toggle="modal" data-target="#del" @click="nowIndex=index">删除</button> </td> </tr> <tr > <td colspan="5" class="text-right"> <button class="btn btn-danger " data-toggle="modal" data-target="#del" @click="nowIndex=-1">删除所有</button></td> </tr> </tbody> </table> <!-- 模态框,弹出框 --> <div class="modal fade" id="del"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button class="close" data-dismiss="modal"> <span>×</span> </button> <div class="modat-titile" v-show="nowIndex!==-1">确定要删除{{users[nowIndex]?users[nowIndex].name:''}}吗?</div> <div class="modat-titile" v-show="nowIndex===-1">确定要删除所有用户吗?</div> </div> <div class="modal-body text-center"> <button class="btn btn-primary" data-dismiss="modal">取消</button> <button class="btn btn-primary" data-dismiss="modal" @click="deletUser">确定</button> </div> </div> </div> </div> </div> <script type="text/javascript"> new Vue({ el:".container", data:{ users:[ {name:'蜡笔小新',age:'5',email:'110@110.com'}, {name:'樱桃小丸子',age:'3',email:'120@120.com'} ], user:{}, nowIndex:-1 }, methods:{ addUser:function(){ this.users.push(this.user); this.user={}; }, deletUser:function(){ if (this.nowIndex===-1) { this.users=[]; }else{ this.users.splice(this.nowIndex,1); } } } }); </script> </body> </html>
{{msg}} <!-- 两对大括号{{}}称为模板,用来进行数据的绑定显示在页面中 -->
//配置是否允许vue-devtools检查代码,方便调试,默认为true,生产环境中需要设置为false
Vue.config.devtools=false;
//阻止vue启动时生成生产消息(提示消息)
Vue.config.productionTip=false;
事件对象$event
包含事件相关信息,如事件源、事件类型、偏移量
target、type、offsetx
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件简写和事件对象$event</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> <button @click="print($event)" >点我</button> </div> <script type="text/javascript"> new Vue({ el:"#app", methods:{ print:function(e){ console.log(e.target.innerHTML); //点我 } } }); </script> </body> </html>
阻止事件冒泡:
a)原生js方式,依赖于事件对象 e.stopPropagation();
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件冒泡和默认行为</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <div @click="show3()"> <p @click="show2()"> <button @click="show1($event)">点我</button> </p> </div> </div> <script type="text/javascript"> new Vue({ el:".app", methods:{ show1:function(e){ e.stopPropagation(); console.log("11111"); }, show2:function(){ console.log("22222"); }, show3:function(){ console.log("33333"); }, } }); </script> </body> </html>
b)vue方式,不依赖于事件对象e.preventDefault();
@click.stop
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件冒泡和默认行为</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <div @click="show3()"> <p @click="show2()"> <button @click.stop="show1()">点我</button> </p> </div> </div> <script type="text/javascript"> new Vue({ el:".app", methods:{ show1:function(){ console.log("11111"); }, show2:function(){ console.log("22222"); }, show3:function(){ console.log("33333"); }, } }); </script> </body> </html>
阻止默认行为:
a)原生js方式,依赖于事件对象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件冒泡和默认行为</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <a href="https://www.baidu.com" title="" @click="change($event)">默认跳转到百度</a> </div> <script type="text/javascript"> new Vue({ el:".app", methods:{ change:function(e){ e.preventDefault(); } } }); </script> </body> </html>
vue方式 @click.prevent
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件冒泡和默认行为</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <a href="https://www.baidu.com" title="" @click.prevent="change()">默认跳转到百度</a> </div> <script type="text/javascript"> new Vue({ el:".app", methods:{ change:function(){ console.log('不跳转'); } } }); </script> </body> </html>
键盘事件<!-- 键盘事件:@keydown、@keypress、@keyup -->
原生js 按键的判断(回车)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>键盘事件</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <input type="text" @keydown="show($event)"> </div> <script type="text/javascript"> new Vue({ el:".app", methods:{ show:function(e){ if(e.keyCode==13){ console.log('你按了回车键'); } } } }); </script> </body> </html>
vue方式按键的判断(回车) 简化按键的判断
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>键盘事件</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <input type="text" @keydown.13="show()"> </div> <script type="text/javascript"> new Vue({ el:".app", methods:{ show:function(){ console.log('你按了回车键'); } } }); </script> </body> </html>
回车:@keydown.13 或@keydown.enter
上:@keydown.38 或@keydown.up
默认没有@keydown.a/b/c...事件,可以自定义键盘事件,也称为自定义键码或自定义键位别名
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>键盘事件</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <input type="text" @keydown.a="show()"> <input type="text" @keydown.f1.prevent="show1()"> </div> <script type="text/javascript"> Vue.config.keyCodes={ a:65, f1:112 } new Vue({ el:".app", methods:{ show:function(){ console.log('你按了a键'); }, show1:function(){ console.log('你按了f1键'); } } }); </script> </body> </html>
事件修饰符
.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
input的修饰符
v-model.lazy.number.trim
属性绑定和属性的简写
v-bind 用于属性绑定, v-bind:属性=""
属性的简写:
v-bind:src="" 简写为 :src=""
vue实例的属性和方法
### 1. 属性
vm.$el vm.$data vm.$options vm.$refs
### 2. 方法
vm.$mount() vm.$destroy() vm.$nextTick(callback)
vm.$set(object,key,value) vm.$delete(object,key) vm.$watch(data,callback[,options])
能在vue之外通过vue实例的属性vm.$data直接访问vue内的数据等属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue实例的属性和方法</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> </div> <script> var vm = new Vue({ el:'.app', data:{ msg:'彭彭' } }); console.log(vm.$data.msg); console.log(vm.msg); </script> </body> </html>
//vm.$el 获取vue实例关联的元素
// console.log(vm.$el); //DOM对象
// vm.$el.style.color='red';
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue实例的属性和方法</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> ddd </div> <script> var vm = new Vue({ el:'.app', data:{ msg:'彭彭' } }); console.log(vm.$el); vm.$el.style.color='red'; </script> </body> </html>
//vm.$options //获取自定义属性
// console.log(vm.$options.name);
// console.log(vm.$options.age);
// vm.$options.show();
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue实例的属性和方法</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> ddd </div> <script> var vm = new Vue({ el:'.app', data:{ msg:'彭彭' }, name:'peng', age:18, show:function(){ console.log("show"); } }); console.log(vm.$options.name); console.log(vm.$options.age); console.log(vm.$options.show); </script> </body> </html>
//vm.$refs 获取所有添加ref属性的元素
// console.log(vm.$refs);
// console.log(vm.$refs.hello); //DOM对象
// vm.$refs.hello.style.color='blue';
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue实例的属性和方法</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <div ref="hello1">hello</div> <div ref="hello2">好</div> </div> <script> var vm = new Vue({ el:'.app', data:{ msg:'彭彭' } }); console.log(vm.$refs); console.log(vm.$refs.hello1); vm.$refs.hello1.style.color="red"; </script> </body> </html>
2. 方法 vm.$mount() vm.$destroy() vm.$nextTick(callback)
vm.$set(object,key,value) vm.$delete(object,key) vm.$watch(data,callback[,options])
/**
* 方法
*/
//vm.$mount() 手动挂载vue实例
// vm.$mount('#itany');
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue实例的方法</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> {{msg}} </div> <script> var vm = new Vue({ data:{ msg:'彭彭' } }); vm.$mount('.app'); </script> </body> </html>
//vm.$destroy() 销毁实例 数据还在
// vm.$destroy();
// vm.$nextTick(callback) 在DOM更新完成后再执行回调函数,一般在修改数据之后使用该方法,以便获取更新后的DOM
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue实例的方法</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <h1 ref="title">标题{{msg}}</h1> </div> <script> var vm = new Vue({ el:'.app', data:{ msg:'彭彭' } }); vm.msg='语文'; //DOM还没更新完,Vue实现响应式并不是数据发生改变之后DOM立即变化,需要按一定的策略进行DOM更新,需要时间!! console.log(vm.$refs.title.textContent); vm.$nextTick(function(){ //DOM更新完成,更新完成后再执行此代码 console.log(vm.$refs.title.textContent); }); </script> </body> </html>
vm.$set(object,key,value) 增加属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加和删除属性:$set、$delete</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <button @click="upData()">更新name</button> <button @click="addData()">增加属性</button> <h2>{{user.name}}</h2> <h1>{{user.age}}</h1> </div> <script> var vm = new Vue({ el:'.app', data:{ user:{ id:1110, name:'peng', } }, methods:{ upData:function(){ this.user.name="cai"; }, addData:function(){ //通过普通方式为对象添加属性时vue无法实时监视到 // this.user.age=18; // console.log(this.user.age); //通过vue实例的$set方法为对象添加属性,可以实时监视,显示在{{}}里 // this.$set(this.user,'age',18); // console.log(this.user.age); if(this.user.age){ this.user.age++; }else{ //全局 Vue.set(this.user,'age',1); } } } }); </script> </body> </html>
vm.$delete(object,key)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加和删除属性:$set、$delete</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <button @click="delData()">删除属性</button> <h2>{{user.name}}</h2> <h1>{{user.age}}</h1> </div> <script> var vm = new Vue({ el:'.app', data:{ user:{ id:1110, name:'peng', age:18 } }, methods:{ delData:function(){ if(this.user.age){ vm.$delete(this.user,'age'); } } } }); </script> </body> </html>
监视数据的变化使用vm.$watch(data,callback[,options])
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>监视数据的变化:$watch</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <input type="text" v-model="msg"> <h1>{{msg}}</h1> <input type="text" v-model="msg2"> <h1>{{msg2}}</h1> <input type="text" v-model="user.name"> <h3>{{user.name}}</h3> </div> <script> vm = new Vue({ el:".app", data:{ msg:'彭', msg2:'msg2', user:{ name:'peng', age:18 } }, watch:{ //方式2:使用vue实例提供的watch选项 msg2:function(newValue,oldValue){ console.log("msg被修改了,原值:"+oldValue+" 新值:"+newValue); }, //深度监视,当对象中的属性发生变化时也会监视 user:{ handler:function(newValue,oldValue){ console.log("msg被修改了,原值:"+oldValue.name+" 新值:"+newValue.name); }, deep:true } } }); //方式1:使用vue实例提供的$watch()方法 vm.$watch('msg',function(newValue,oldValue){ console.log("msg被修改了,原值:"+oldValue+" 新值:"+newValue); }); </script> </body> </html>
自定义指令 分类:全局指令、局部指令
### 1. 自定义全局指令 使用全局方法Vue.directive(指令ID,定义对象)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>自定义指令</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <p v-peng:wbs110.heh.hah="msg">{{msg}}</p> <button @click="change">更新数据</button> </div> <script> Vue.directive('peng',{ bind:function(el,binding){ console.log(el); //指令所绑定的元素,DOM对象 el.style.color="red"; console.log(binding); console.log('这是通过指令传经来的vue里的数据:'+binding.value); console.log('这是通过指令传经来的参数:'+binding.arg); console.log('这是通过指令传经来的修饰符:'+binding.modifiers.heh); alert('指令第一次绑定到元素上,且只执行一次,一般用于初始化!'); }, inserted:function(){ alert('被绑定元素插入到DOM时执行'); }, update:function(){ alert('被绑定元素所在的模板更新时执行'); }, componentUpdated:function(){ alert('被绑定元素所在的模板完成一次更新周期时执行'); }, unbind(){ alert('指令与元素解绑时调用,只调用一次'); } }); //传入一个简单的函数,bind和update时调用 Vue.directive('wbs',function(){ alert('wbs17022'); }); var vm=new Vue({ el:".app", data:{ msg:"彭彭" }, methods:{ change:function(){ this.msg="peng"; } } }); </script> </body> </html>
### 2. 自定义局部指令
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>自定义指令</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <input type="text" v-model="msg" v-focus> </div> <script> var vm=new Vue({ el:".app", data:{ msg:"彭彭" }, methods:{ change:function(){ this.msg="peng"; } }, directives:{ //自定义局部指令 focus:{ //当被绑定元素插入到DOM中时获取焦点 inserted:function(el){ el.focus(); } } } }); </script> </body> </html>
### 3. 练习 拖动页面中的元素 onmouseover onmouseout onmousedown onmousemove onmouseup
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>自定指令实现拖拽</title> <script src="js/vue.js"></script> <style type="text/css"> .aa{ width:100px; height: 100px; background: red; position:absolute; } </style> </head> <body> <div class="app"> <div :class="{aa:true}" v-drag > </div> </div> <script> Vue.directive('drag',function(el){ el.onmousedown=function(e){ var disX=e.clientX-el.offsetLeft; var disY=e.clientY-el.offsetTop; document.onmousemove=function(e){ el.style.left=(e.clientX-disX)+'px'; el.style.top=(e.clientY-disY)+'px'; } document.onmouseup=function(e){ document.onmousemove=null; document.onmouseup=null; } } }); new Vue({ el:".app", }); </script> </body> </html>
过渡(动画)
### 1. 简介
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果
本质上还是使用CSS3动画:transition、animation
### 2. 基本用法
使用transition组件,将要执行动画的元素包含在该组件内
<transition>
运动的元素
</transition>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>动画</title> <script src="js/vue.js"></script> </head> <style type="text/css"> p{ width: 300px; height: 300px; background: red; } .fade-enter-active,.fade-leave-active{ transition: all 1s ease; } .fade-enter-active{ opacity: 1; width: 300px; height: 300px; } .fade-leave-active{ opacity: 1; width: 100px; height: 100px; } .fade-enter{ opacity: 0; height: 50px; width: 50px; } </style> <body> <div class="app"> <button @click="flag=!flag">切换</button> <transition name="fade" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter" @before-leave="beforeLeave" @leave="leave" @after-leave="afterLeave" > <p v-show="flag"></p> </transition> </div> <script> new Vue({ el:".app", data:{ flag:false }, methods:{ beforeEnter(el){ alert('动画进入之前'); }, enter(){ // alert('动画进入'); }, afterEnter(el){ // alert('动画进入之后'); el.style.background='blue'; }, beforeLeave(){ // alert('动画即将之前'); }, leave(){ // alert('动画离开'); }, afterLeave(el){ // alert('动画离开之后'); el.style.background='red'; } } }); </script> </body> </html>
过滤的CSS类名:6个
### 3. 钩子函数
8个
### 4. 结合第三方动画库animate..css一起使用
<transition enter-active-class="animated fadeInLeft" leave-active-class="animated fadeOutRight">
<p v-show="flag">网博</p>
</transition>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>动画</title> <link rel="stylesheet" href="css/animate.css"> <script src="js/vue.js"></script> <style> p{ width: 100px; height: 100px; background: red; margin: 20px auto; } </style> </head> <body> <div class="app"> <button @click="flag=!flag">切换</button> <transition enter-active-class='animated hinge' leave-active-class='animated fadeOutRight'> <p v-show="flag"></p> </transition> </div> <script> new Vue({ el:".app", data:{ flag:false } }); </script> </body> </html>
### 5. 多元素动画
<transition-group>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>动画</title> <link rel="stylesheet" href="css/animate.css"> <script src="js/vue.js"></script> <style> p{ width: 100px; height: 100px; background: red; margin: 20px auto; } </style> </head> <body> <div class="app"> <button @click="flag=!flag">切换</button> <transition-group enter-active-class='animated hinge' leave-active-class='animated fadeOutRight'> <p v-show="flag" :key="1"></p> <p v-show="flag" :key="2"></p> </transition-group> </div> <script> new Vue({ el:".app", data:{ flag:false } }); </script> </body> </html>
### 6. 练习
多元素动画
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>练习:多元素动画</title> <link rel="stylesheet" href="css/animate.css"> <script src="js/vue.js"></script> <style> p{ width: 100px; height: 100px; background-color:red; margin:20px auto; } </style> </head> <body> <div id="itany"> <input type="text" v-model="name"> <transition-group enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight"> <p v-for="(v,k) in arr2" :key="k"> {{v}} </p> </transition-group> </div> <script> var vm=new Vue({ el:'#itany', data:{ flag:true, arr:['tom','jack','mike','alice','alex','mark'], name:'' }, computed:{ arr2:function(){ var temp=[]; this.arr.forEach(val => { if(val.includes(this.name)){ temp.push(val); } }); return temp; } } }); </script> </body> </html>
## 一、 组件component
### 1. 什么是组件?
组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码
组件是自定义元素(对象)
### 2. 定义组件的方式
方式1:先创建组件构造器,然后由组件构造器创建组件
方式2:直接创建组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>定义组件的两种方式</title> <script src="js/vue.js"></script> </head> <body> <div id="itany"> <hello></hello> <my-world></my-world> </div> <script> /** * 方式1:先创建组件构造器,然后由组件构造器创建组件 */ //1.使用Vue.extend()创建一个组件构造器 var MyComponent=Vue.extend({ template:'<h3>Hello World</h3>' }); //2.使用Vue.component(标签名,组件构造器),根据组件构造器来创建组件 Vue.component('hello',MyComponent); /** * 方式2:直接创建组件(推荐) */ // Vue.component('world',{ Vue.component('my-world',{ template:'<h1>你好,世界</h1>' }); var vm=new Vue({ //这里的vm也是一个组件,称为根组件Root el:'#itany', data:{ msg:'网博' } }); </script> </body> </html>
### 3. 组件的分类
分类:全局组件、局部组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>组件的分类</title> <script src="js/vue.js"></script> </head> <body> <div id="itany"> <my-hello></my-hello> <my-world></my-world> </div> <script> /** * 全局组件,可以在所有vue实例中使用 */ Vue.component('my-hello',{ template:'<h3>{{name}}</h3>', data:function(){ //在组件中存储数据时,必须以函数形式,函数返回一个对象 return { name:'alice' } } }); /** * 局部组件,只能在当前vue实例中使用 */ var vm=new Vue({ el:'#itany', data:{ name:'tom' }, components:{ //局部组件 'my-world':{ template:'<h3>{{age}}</h3>', data(){ return { age:25 } } } } }); </script> </body> </html>
### 4. 引用模板
将组件内容放到模板<template>中并引用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>引用模板</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <my-comp></my-comp> <my-comp></my-comp> </div> <template id="tem"> <div> <h3>{{msg}}</h3> <ul> <li v-for="value in arr">{{value}}</li> </ul> </div> </template> <script> new Vue({ el:".app", components:{ 'my-comp':{ template:'#tem', name:'wbs17022', //指定组件的名称,默认为标签名,可以不设置 data:function(){ return { msg:'我的组件', arr:['aa','bb','cc'] } } } } }); </script> </body> </html>
### 5. 动态组件
<component :is="">组件
多个组件使用同一个挂载点,然后动态的在它们之间切换
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>动态组件</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <button @click="flag='my-comp1'">组件1显示</button> <button @click="flag='my-comp2'">组件2显示</button> <div> <component :is="flag"></component> </div> </div> <script> new Vue({ el:'.app', data:{ flag:'my-comp1' }, components:{ "my-comp1":{ template:"<h3>组件1</h3>" }, "my-comp2":{ template:"<h1>组件2</h1>" } } }); </script> </body> </html>
<keep-alive>组件 <!-- 使用keep-alive组件缓存非活动组件,可以保留状态,避免重新渲染,默认每次都会销毁非活动组件并重新创建 -->
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>动态组件</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <button @click="flag='my-comp1'">组件1显示</button> <button @click="flag='my-comp2'">组件2显示</button> <div> <keep-alive> <component :is="flag"></component> </keep-alive> </div> </div> <script> new Vue({ el:'.app', data:{ flag:'my-comp1' }, components:{ "my-comp1":{ template:"<h3>组件1 {{x}}</h3>", data:function(){ return { x:Math.random() } } }, "my-comp2":{ template:"<h1>组件2 {{y}}</h1>", data:function(){ return { y:Math.random() } } } } }); </script> </body> </html>
组件间数据传递
### 1. 父子组件
在一个组件内部定义另一个组件,称为父子组件
子组件只能在父组件内部使用
默认情况下,子组件无法访问父组件中的数据,父组件也无法访问子组件的数据,每个组件实例的作用域是独立的
### 2. 组件间数据传递 (通信)
#### 2.1 子组件访问父组件的数据
a)在调用子组件时,绑定想要获取的父组件中的数据
b)在子组件内部,使用props选项声明获取的数据,即接收来自父组件的数据
总结:父组件通过props向下传递数据给子组件
注:组件中的数据共有三种形式:data、props、computed
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>父子组件及组件间数据传递</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <far-comp></far-comp> </div> <template id="far"> <div> <h3>我是父组件,访问自己的数据:{{farmsg}}</h3> <son-comp :message="farmsg"></son-comp> </div> </template> <template id="son"> <div> <h3>我是子组件,访问自己的数据:{{sonmsg}}</h3> <h3>我是子组件,访问父组件的数据:{{message}}</h3> </div> </template> <script> new Vue({ el:'.app', components:{ "far-comp":{ template:"#far", data:function(){ return { farmsg:'数据farmsg' } }, components:{ "son-comp":{ template:"#son", props:{ message:String }, data:function(){ return{ sonmsg:'数据sonmsg' } } } } } } }); </script> </body> </html>
#### 2.2 父组件访问子组件的数据
a)在子组件中使用vm.$emit(事件名,数据)触发一个自定义事件,事件名自定义
b)父组件在使用子组件的地方监听子组件触发的事件,并在父组件中定义方法,用来获取数据
总结:子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>父子组件及组件间数据传递</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <far-comp></far-comp> </div> <template id="far"> <div> <h3>我是父组件,访问自己的数据:{{farmsg}}</h3> <h3>我是父组件,访问子组件的数据:{{sonmsg}}</h3> <son-comp @my-emit="getData" ></son-comp> </div> </template> <template id="son"> <div> <h3>我是子组件,访问自己的数据:{{sonmsg}}</h3> <button @click="send()">触发自定义事件发送子组件数据</button> </div> </template> <script> new Vue({ el:'.app', components:{ "far-comp":{ template:"#far", data:function(){ return { farmsg:'数据farmsg', sonmsg:'' } }, methods:{ getData:function(sonmsg){ console.log(sonmsg); this.sonmsg=sonmsg; } }, components:{ "son-comp":{ template:"#son", data:function(){ return{ sonmsg:'数据sonmsg' } }, methods:{ send:function(){ console.log(this.sonmsg); //此处的this表示当前子组件实例 console.log("执行了send()函数"); this.$emit('my-emit',this.sonmsg);//使用$emit()触发一个事件,发送数据 } } } } } } }); </script> </body> </html>
### 3. 单向数据流
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>单向数据流</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <h3>我是父组件,我的数据是{{msg}}</h3> <son-comp :msg="msg"></son-comp> </div> <template id="son"> <div> <h1>我是子组件,我的数据是:{{sonmsg}}</h1> <h1>我是子组件,我接收父组件数据是:{{msg}}</h1> </div> </template> <script> var vm = new Vue({ el:".app", data:{ msg:'父数据msg' }, components:{ 'son-comp':{ template:"#son", props:{ msg:String }, data:function(){ return { sonmsg:"子数据sonmsg", } } } } }); </script> </body> </html>
props是单向绑定的,当父组件的属性变化时,将传导给子组件,但是不会反过来
而且不允许子组件直接修改父组件中的数据,报错
解决方式:
方式1:如果子组件想把它作为局部数据来使用,可以将数据存入另一个变量中再操作,不影响父组件中的数据
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>子组件想把从父组件得到的数据作为局部数据来使用</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <h3>我是父组件,我的数据是{{msg}}</h3> <son-comp :msg="msg"></son-comp> </div> <template id="son"> <div> <h1>我是子组件,我的数据是:{{sonmsg}}</h1> <h1>我是子组件,我接收父组件数据是:{{msg}}</h1> <h1>我是子组件,我接收父组件数据存到自己的data里:{{sonFar}}</h1> <input type="text" v-model="sonFar"> </div> </template> <script> var vm = new Vue({ el:".app", data:{ msg:'父数据msg' }, components:{ 'son-comp':{ template:"#son", props:{ msg:String }, data:function(){ return { sonmsg:"子数据sonmsg", sonFar:this.msg } } } } }); </script> </body> </html>
方式2:如果子组件想修改数据并且同步更新到父组件,两个方法:
a.使用.sync(1.0版本中支持,2.0版本中不支持,2.3版本又开始支持)
需要显式地触发一个更新事件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>子组件想修改数据并且同步更新到父组件</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <h3>我是父组件,我的数据是{{msg}}</h3> <son-comp :msg.sync="msg"></son-comp> </div> <template id="son"> <div> <h1>我是子组件,我的数据是:{{sonmsg}}</h1> <h1>我是子组件,我接收父组件数据是:{{msg}}</h1> <button @click="change()">子组件修改接收到父组件数据</button> </div> </template> <script> var vm = new Vue({ el:".app", data:{ msg:'父数据msg' }, components:{ 'son-comp':{ template:"#son", props:{ msg:String }, data:function(){ return { sonmsg:"子数据sonmsg", } }, methods:{ change:function(){ this.$emit('update:msg','子组件修改接收到父组件数据msg'); } } } } }); </script> </body> </html>
b.可以将父组件中的数据包装成对象,然后在子组件中修改对象的属性(因为对象是引用类型,指向同一个内存空间),推荐
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>子组件想修改数据并且同步更新到父组件(推荐)</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <h3>我是父组件,我的数据是{{user.msg}}</h3> <son-comp :user="user"></son-comp> </div> <template id="son"> <div> <h1>我是子组件,我的数据是:{{sonmsg}}</h1> <h1>我是子组件,我接收父组件数据是:{{user.msg}}</h1> <button @click="change()">子组件修改接收到父组件数据</button> </div> </template> <script> var vm = new Vue({ el:".app", data:{ user:{ msg:'父数据msg' } }, components:{ 'son-comp':{ template:"#son", props:['user'], data:function(){ return { sonmsg:"子数据sonmsg", } }, methods:{ change:function(){ this.user.msg="子组件修改接收到父组件数据"; } } } } }); </script> </body> </html>
### 4. 非父子组件间的通信
非父子组件间的通信,可以通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件
var Event=new Vue();
Event.$emit(事件名,数据);
Event.$on(事件名,data => {});
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>非父子组件间的通信(数据比较简单时使用)</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <a-comp></a-comp> <b-comp></b-comp> </div> <template id="a"> <div> <h3>我是a组件,我的数据是:{{msg}}</h3> <button @click="change()">把自己的数据msg发出去</button> </div> </template> <template id="b"> <h1>我是b组件,我接收的数据是:{{msg}}</h1> </template> <script> var bush=new Vue(); new Vue({ el:".app", components:{ 'a-comp':{ template:"#a", data:function(){ return { msg:"a组件的msg" } }, methods:{ change:function(){ bush.$emit('e-send',this.msg); } } }, 'b-comp':{ template:"#b", data:function(){ return { msg:'' } }, mounted:function(){ //这里不能用function(msg){因为这里面的this指向调用它bush,而不是指向b-comp。所以要用msg=>,不改变this。还要注意:监听一定要在触发e-send事件之前,否则会监听不到e-send事件带来的数据} bush.$on('e-send',msg=>{ this.msg=msg; }); } } } }); </script> </body> </html>
slot内容分发
本意:位置、槽
作用:用来获取组件中的原内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>slot内容分发</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <my-comp>我是组件里填的内容</my-comp> </div> <template id="my"> <div> <h3>我是组件</h3> <slot></slot> </div> </template> <script> new Vue({ el:".app", components:{ "my-comp":{ template:'#my', } } }); </script> </body> </html>
组件里的内容会替换slot里的内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>slot内容分发</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <my-comp>我是组件里填的内容</my-comp> </div> <template id="my"> <div> <h3>我是组件</h3> <slot>我是slot里的内容</slot> </div> </template> <script> new Vue({ el:".app", components:{ "my-comp":{ template:'#my', } } }); </script> </body> </html>
具名solt:决定组件里的内容是否显示以及显示的位置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>slot内容分发</title> <script src="js/vue.js"></script> </head> <body> <div class="app"> <my-comp> <div slot="content1"> 我是内容一 </div> <div> 我是内容二 </div> </my-comp> </div> <template id="my"> <div> <h3>我是组件</h3> <slot name="content1"></slot> </div> </template> <script> new Vue({ el:".app", components:{ "my-comp":{ template:'#my', } } }); </script> </body> </html>
vue-router路由
### 1. 简介
使用Vue.js开发SPA(Single Page Application)单页面应用
根据不同url地址,显示不同的内容,但显示在同一个页面中,称为单页面应用
[参考](https://router.vuejs.org/zh-cn)
bower info vue-router
cnpm install vue-router -S
### 2. 基本用法
a.布局
b.配置路由
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>路由基本用法</title> <script src="js/vue.js"></script> <script src="js/vue-router.js"></script> </head> <body> <div class="app"> <div> <router-link to="/us">我们</router-link> <router-link to="/news">新闻</router-link> </div> <div> <router-view></router-view> </div> </div> <script> var Us={ template:"<h1>联系我们</h1>" }; var News={ template:"<h3>新闻内容</h3>" }; const routes=[ {path:'/us',component:Us}, {path:'/news',component:News} ]; const router = new VueRouter({ routes:routes }); new Vue({ el:".app", router:router }); </script> </body> </html>
模式、激活class、重定向
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>路由基本用法</title> <script src="js/vue.js"></script> <script src="js/vue-router.js"></script> <style type="text/css"> .router-link-active{ text-decoration: none; font-size: 36px; color: red; } </style> </head> <body> <div class="app"> <div> <router-link to="/us">我们</router-link> <router-link to="/news">新闻</router-link> </div> <div> <router-view></router-view> </div> </div> <script> var Us={ template:"<h1>联系我们</h1>" }; var News={ template:"<h3>新闻内容</h3>" }; const routes=[ {path:'*',redirect:'/us'}, {path:'/us',component:Us}, {path:'/news',component:News} ]; const router = new VueRouter({ routes:routes, // mode:"history", // linkActiveClass:'active' //更新活动链接的class类名 }); new Vue({ el:".app", router:router }); </script> </body> </html>
### 3. 路由嵌套和参数传递
路由嵌套
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>路由嵌套</title> <script src="js/vue.js"></script> <script src="js/vue-router.js"></script> <style type="text/css"> .router-link-active{ font-size:20px; color:#ff7300; text-decoration:none; } </style> </head> <body> <div class="app"> <div> <router-link to="/home">主页</router-link> <router-link to="/user">用户</router-link> </div> <div> <router-view></router-view> </div> </div> <template id="user"> <div> <h3>用户信息</h3> <ul> <router-link to="/user/login" tag="li">注册</router-link> <router-link to="/user/regist" tag="li">登陆</router-link> </ul> <router-view></router-view> </div> </template> <script type="text/javascript"> var Home={ template:"<h3> 主页内容</h3>" }; var User={ template:"#user" // template:"<h2>yon</h2>" }; var Regist={ template:"<h1>登陆页面。。。。</h1>" }; var Login={ template:"<h1>注册页面。。。</h1>" }; const routes=[ { path:"/Home", component:Home }, { path:"/user", component:User, children:[ { path:'regist', component:Regist }, { path:'login', component:Login } ] } ]; const router=new VueRouter({ routes:routes }); new Vue({ el:".app", router:router }); </script> </body> </html>
传参的两种形式:
a.查询字符串:login?name=tom&pwd=123
{{$route.query}}
b.rest风格url:regist/alice/456
{{$route.params}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>路由传参数</title> <script src="js/vue.js"></script> <script src="js/vue-router.js"></script> <style type="text/css"> .router-link-active{ font-size:20px; color:#ff7300; text-decoration:none; } </style> </head> <body> <div class="app"> <div> <router-link to="/home">主页</router-link> <router-link to="/user">用户</router-link> </div> <div> <router-view></router-view> </div> </div> <template id="user"> <div> <h3>用户信息</h3> <ul> <router-link to="/user/login?name=peng&pwd=123" tag="li">注册</router-link> <router-link to="/user/regist/peng/123" tag="li">登陆</router-link> </ul> <router-view></router-view> </div> </template> <script type="text/javascript"> var Home={ template:"<h3> 主页内容</h3>" }; var User={ template:"#user" }; var Regist={ template:"<h1>登陆页面。。。。获取的参数是:{{$route.params}}</h1>" }; var Login={ template:"<h1>注册页面。。。获取的参数是:{{$route.query}}</h1>" }; const routes=[ { path:"/Home", component:Home }, { path:"/user", component:User, children:[ { path:'regist/:name/:pwd', component:Regist }, { path:'login', component:Login } ] } ]; const router=new VueRouter({ routes:routes }); new Vue({ el:".app", router:router }); </script> </body> </html>
### 4. 路由实例的方法
router.push() 添加路由,功能上与<route-link>相同
router.replace() 替换路由,不产生历史记录
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>路由切换</title> <script src="js/vue.js"></script> <script src="js/vue-router.js"></script> <style type="text/css"> .router-link-active{ font-size:20px; color:#ff7300; text-decoration:none; } </style> </head> <body> <div class="app"> <div> <router-link to="/home">主页</router-link> <router-link to="/user">用户</router-link> </div> <div> <router-view></router-view> </div> <button @click="change()">切换路由</button> <button @click="replace()">替换路由</button> </div> <template id="user"> <div> <h3>用户信息</h3> <ul> <router-link to="/user/login" tag="li">注册</router-link> <router-link to="/user/regist" tag="li">登陆</router-link> </ul> <router-view></router-view> </div> </template> <script type="text/javascript"> var Home={ template:"<h3> 主页内容</h3>" }; var User={ template:"#user" // template:"<h2>yon</h2>" }; var Regist={ template:"<h1>登陆页面。。。。</h1>" }; var Login={ template:"<h1>注册页面。。。</h1>" }; const routes=[ { path:"/home", component:Home }, { path:"/user", component:User, children:[ { path:'regist', component:Regist }, { path:'login', component:Login } ] } ]; const router=new VueRouter({ routes:routes }); new Vue({ el:".app", router:router, methods:{ change:function(){ router.push({path:'home'}); }, replace:function(){ router.replace({path:'user'}); } } }); </script> </body> </html>
### 5. 路由结合动画
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>路由结合动画</title> <link rel="stylesheet" href="css/animate.css"> <script src="js/vue.js"></script> <script src="js/vue-router.js"></script> <style type="text/css"> .router-link-active{ font-size:20px; color:#ff7300; text-decoration:none; } </style> </head> <body> <div class="app"> <div> <router-link to="/home">主页</router-link> <router-link to="/user">用户</router-link> </div> <div> <transition enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight"> <transition enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight"> <router-view></router-view> </transition> </div> </div> <template id="user"> <div> <h3>用户信息</h3> <ul> <router-link to="/user/login" tag="li">注册</router-link> <router-link to="/user/regist" tag="li">登陆</router-link> </ul> <router-view></router-view> </div> </template> <script type="text/javascript"> var Home={ template:"<h3> 主页内容</h3>" }; var User={ template:"#user" // template:"<h2>yon</h2>" }; var Regist={ template:"<h1>登陆页面。。。。</h1>" }; var Login={ template:"<h1>注册页面。。。</h1>" }; const routes=[ { path:"/Home", component:Home }, { path:"/user", component:User, children:[ { path:'regist', component:Regist }, { path:'login', component:Login } ] } ]; const router=new VueRouter({ routes:routes }); new Vue({ el:".app", router:router }); </script> </body> </html>
.vue文件
.vue文件,称为单文件组件,是Vue.js自定义的一种文件格式,一个.vue文件就是一个单独的组件,在文件内封装了组件相关的代码:html、css、js
.vue文件由三部分组成:<template>、<style>、<script>
<template>
html
</template>
<style>
css
</style>
<script>
js
</script>
### 2. vue-loader
浏览器本身并不认为.vue文件,所以必须对.vue文件进行加载解析,此时需要vue-loader
类似的loader还有许多,如:html-loader、css-loader、style-loader、babel-loader等
需要注意的是vue-loader是基于webpack的
### 3. webpack
webpack是一个前端资源模板化加载器和打包工具,它能够把各种资源都作为模块来使用和处理
实际上,webpack是通过不同的loader将这些资源加载后打包,然后输出打包后文件
简单来说,webpack就是一个模块加载器,所有资源都可以作为模块来加载,最后打包输出
[官网](http://webpack.github.io/)
webpack版本:v1.x v2.x
webpack有一个核心配置文件:webpack.config.js,必须放在项目根目录下
示例,步骤:
#### 4.1 创建项目,目录结构 如下:
webpack-demo
|-index.html
|-main.js 入口文件
|-App.vue vue文件
|-package.json 工程文件
|-webpack.config.js webpack配置文件
|-.babelrc Babel配置文件
### 4.2 编写App.vue
### 4.3 安装相关模板
cnpm install vue -S
cnpm install webpack -D //生产依赖
cnpm install webpack-dev-server -D // 访问webpack,搭建服务器
cnpm install vue-loader -D
cnpm install vue-html-loader -D
cnpm install css-loader -D
cnpm install vue-style-loader -D
cnpm install file-loader -D //用到字体字库
cnpm install babel-loader -D //ES6语法
cnpm install babel-core -D //核心
cnpm install babel-preset-env -D //根据配置的运行环境自动启用需要的babel插件
cnpm install vue-template-compiler -D //预编译模板
合并:cnpm install -D webpack webpack-dev-server vue-loader vue-html-loader css-loader vue-style-loader file-loader babel-loader babel-core babel-preset-env vue-template-compiler
### 4.4 编写main.js
/**
* 使用ES6语法引入模板
*/
import Vue from 'vue' //会去node_modules去找(vue装在这里),
import App from './App.vue' //虽然在同一目录,但因为它不是内部模块,而是自定义模块,所以要加 ./
new Vue({
el:'#app', //App.vue里要应用
render:function(h){ //使用render函数渲染组件 :组件注册等价与components
return h(App);
}
});
### 4.5 编写webpack.config.js
module.exports={
//配置入口文件
entry:'./main.js',
//配置入口文件输出位置
output:{
path:__dirname, //项目根路径
filename:'build.js'
},
//配置模块加载器
module:{
rules:[
{
test:/.vue$/, //所有以.vue结尾的文件都由vue-loader加载
loader:'vue-loader'
},
{
test:/.js$/, //所有以.js结尾的文件都由babel-loader加载,除了node_modules以外
loader:'babel-loader',
exclude:/node_modules/
}
]
}
}
### 4.6 编写.babelrc
{
"presets":[
["env",{"module":false}]
]
}
### 4.7 编写package.json
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"dev":"webpack-dev-server --open --hot --port 8800"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"vue": "^2.3.4"
},
"devDependencies": {
"babel-core": "^6.25.0",
"babel-loader": "^7.1.1",
"babel-preset-env": "^1.5.2",
"css-loader": "^0.28.4",
"file-loader": "^0.11.2",
"vue-html-loader": "^1.2.4",
"vue-loader": "^13.0.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.3.4",
"webpack": "^3.0.0",
"webpack-dev-server": "^2.5.0"
}
}
### 4.8 运行测试
npm run dev
vue-cli脚手架
### 1. 简介
vue-cli是一个vue脚手架,可以快速构造项目结构
vue-cli本身集成了多种项目模板:
simple 很少简单
webpack 包含ESLint代码规范检查和unit单元测试等
webpack-simple 没有代码规范检查和单元测试
browserify 使用的也比较多
browserify-simple
### 2. 示例,步骤:
#### 2.1 安装vue-cli,配置vue命令环境
cnpm install vue-cli -g
vue --version
vue list
#### 2.2 初始化项目,生成项目模板
语法:vue init 模板名 项目名
#### 2.3 进入生成的项目目录,安装模块包
cd vue-cli-demo
cnpm install
#### 2.4 运行
npm run dev //启动测试服务
npm run build //将项目打包输出dist目录,项目上线的话要将dist目录拷贝到服务器上
### 3. 使用webpack模板
vue init webpack vue-cli-demo2
ESLint是用来统一代码规范和风格的工具,如缩进、空格、符号等,要求比较严格
[官网](http://eslint.org)
问题Bug:如果版本升级到node 8.0 和 npm 5.0,控制台会报错:
GET http://localhost:8080/__webpack_hmr net::ERR_INCOMPLETE_CHUNKED_ENCODING
解决方法:
a)降低Node版本到7.9或以下
b)修改build/dev-server.js文件,如下:
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {},
heartbeat:2000 //添加此行
})
参考:https://github.com/vuejs-templates/webpack/issues/731
一个项目从开始
2.1 安装vue-cli,配置vue命令环境
cnpm install vue-cli -g
vue --version
vue list
#### 2.2 初始化项目,生成项目模板
语法:vue init 模板名(webpack-simple) 项目名
<? License (MIT) no
? License no
? Use sass? (y/N) N
? Use sass? No
>
#### 2.3 进入生成的项目目录,安装模块包
cd vue-cli-demo
cnpm install
#### 2.4 运行
npm run dev //启动测试服务
<用vue-router
cnpm install vue-router -S
>
npm run build //将项目打包输出dist目录,项目上线的话要将dist目录拷贝到服务器上
模块化开发
### 1. vue-router模块化
cnpm install vue-router -S
#### 1.1 编辑main.js
#### 1.2 编辑App.vue
<template> <div id="app"> <div> <router-link to="/home">主页</router-link> <router-link to="/news">新闻</router-link> </div> <keep-alive> <router-view></router-view> </keep-alive> </div> </template> <script> export default { name: 'app', data () { return { msg: 'Welcome to Your Vue.js App' } }, mounted:function(){ console.log(this.$route) }, watch:{ $route:function(newValue,oldValue){ console.log('路由发生了变化,跳转到:'+oldValue.path); } } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
#### 1.3 编辑router.config.js
### 2. axios模块化
cnpm install axios -S
使用axios的两种方式:
方式1:在每个组件中引入axios
<template> <div id="app"> <div> <router-link to="/home">主页</router-link> <router-link to="/news">新闻</router-link> </div> <keep-alive> <router-view></router-view> </keep-alive> <hr> <button @click="send">发送AJAX请求</button> </div> </template> <script> import axios from 'axios' export default { name: 'app', data () { return { msg: 'Welcome to Your Vue.js App' } }, mounted:function(){ console.log(this.$route) }, watch:{ $route:function(newValue,oldValue){ console.log('路由发生了变化,跳转到:'+oldValue.path); } }, methods:{ send:function(){ axios.get('https://api.github.com/users/tangyang8942') .then(function(resp){ console.log(resp); }).catch(function(){ console.log('请求失败'); }); } } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
方式2:在main.js中全局引入axios并添加到Vue原型中
### 3. 为自定义组件添加事件
<Mybutton @click.native="send"></Mybutton>
Elment UI
### 1. 简介
Element UI是饿了么团队提供的一套基于Vue2.0的组件库,可以快速搭建网站,提高开发效率
ElementUI PC端
MintUI 移动端
[官网](http://element.eleme.io/)
### 2. 快速上手
#### 2.1 安装elment ui
cnpm install element-ui -S
#### 2.2 在main.js中引入并使用组件
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css' //该样式文件需要单独引入
Vue.use(ElementUI);
这种方式引入了ElementUI中所有的组件
#### 2.3 在webpack.config.js中添加loader
CSS样式和字体图标都需要由相应的loader来加载,所以需要style-loader、css-loader
默认并没有style-loader模块,所以需要单独安装
cnpm install style-loader --save-dev
<template> <div id="app"> <h1>{{ msg }}</h1> <hr> <el-button type="primary">我的按钮</el-button> <el-button round>圆角按钮</el-button> <el-button icon="el-icon-search" circle></el-button> <el-button type="primary" icon="el-icon-edit" circle></el-button> <el-button type="success" icon="el-icon-check" circle></el-button> <el-button type="info" icon="el-icon-message" circle></el-button> <el-button type="warning" icon="el-icon-star-off" circle></el-button> <el-button type="danger" icon="el-icon-delete" circle></el-button> </div> </template> <script> export default { name: 'app', data () { return { msg: '彭彭' } } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
#### 2.4 使用组件
#### 2.5 使用less
安装loader,需要两个:less、less-loader
cnpm install less less-loader -D
在webpack.config.js中添加loader
### 3. 按需引入组
#### 3.1 安装babel-plugin-component
cnpm install babel-plugin-component -D
#### 3.2 配置.babelrc文件
"plugins": [["component", [
{
"libraryName": "element-ui",
"styleLibraryName": "theme-default"
}
]]]
#### 3.3 只引入需要的插件
## 三、 自定义全局组件(插件)
全局组件(插件):就是指可以在main.js中使用Vue.use()进行全局引入,然后在其他组件中就都可以使用了,如vue-router
import VueRouter from 'vue-router'
Vue.use(VueRouter);
普通组件(插件):每次使用时都要引入,如axios
import axios from 'axios'
Vuex
### 1. 简介
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
简单来说,用来集中管理数据,类似于React中的Redux,都是基于Flux的前端状态管理框架
### 2. 基本用法
#### 2.1 安装vuex
cnpm install vuex -S
#### 2.2 创建store.js文件,在main.js中导入并配置store.选项
#### 2.3 编辑store.js文件
Vuex的核心是Store(仓库),相当于是一个容器,一个store实例中包含以下属性的方法:
state 定义属性(状态、数据)
getters 用来获取属性
actions 定义方法(动作)
commit 提交变化,修改数据的唯一方式就是显式的提交mutations
mutations 定义变化
注:不能直接修改数据,必须显式提交变化,目的是为了追踪到状态的变化
#### 2.4 编辑App.vue
在子组件中访问store对象的两种方式:
方式1:通过this.$store访问
方式2:通过mapState、mapGetters、mapActions访问,vuex提供了两个方法:
mapState 获取state
mapGetters 获取getters
mapActions 获取actions
### 3. 分模块组织Vuex
|-src
|-store
|-index.js
|-getters.js
|-actions.js
|-mutations.js
|-modules //分为多个模块,每个模块都可以拥有自己的state、getters、actions、mutations
|-user.js
|-cart.js
|-goods.js
|....
## 一、 准备工作
###1. 初始化项目
vue init webpack itany
cd itany
cnpm install
cnpm install less less-loader -D
cnpm install vuex axios -S
npm run dev
### 2. 项目资源
|-reset.css
|-data.json
### 3. 创建目录结构
首先清除项目中的部分内容
创建如下目录结构:
|-data.json
|-static
|-css
|-reset.css
### 4. 配置API接口,模拟后台数据
使用express框架启动一个Node服务器,配置API接口,模拟后台数据
测试API:
http://localhost:8080/api/seller
http://localhost:8080/api/goods
http://localhost:8080/api/ratings
## 二、项目整体结构开发