vue学习记录
vue中常用的指令
v-model
双向数据绑定,一般用于表单元素
v-for
对数组或对象进行循环操作,使用的是v-for
<!-- 普通循环 -->
<li v-for="value in arr">{{value}}</li>
<!-- 键值循环 -->
<li v-for="(v,k) in arr">{{k}}={{v}}</li>
<!-- 可以直接循环包含重复数据的集合,可以通过指定:key属性绑定唯一key,当更新元素时可重用元素,提高效率 ,变化的替换,不变的不替换
官方解释:当 Vue.js 用 v-for
正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在 特定索引下显示已被渲染过的每个元素。
-->
<li v-for="(v,k) in arr2" :key="k">{{v}}</li>
<li v-for="(user,index) in users">
{{index+1}},{{user.id}},{{user.name}},{{user.age}}
</li>
v-on
用来绑定事件,用法:v-on:事件="函数" v-on:click="" 简写方式 @click="" vue方法里的this表示当前vue实例 vue方法访问vue方法或数据都要用this,不能直接访问
v-show/v-if
用来显示或隐藏元素,v-show是通过display实现,v-if是每次删除后再重新创建
指令能直接访问vue实例中的数据
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<script src="js/vue.js"></script>
<link rel="stylesheet" href="">
</head>
<body> <div id="app">
<button @click="flag=!flag">显示或隐藏</button> <div style="width: 100px;height: 100px;background: red;" v-if="flag"></div>
</div> <script type="text/javascript">
window.onload=function(){
new Vue({
el:"#app",
data:{
flag:false
}
});
}
</script> </body>
</html>
用户管理例子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
<script src="js/vue.js"></script>
<link rel="stylesheet" href="bootstrap/bootstrap.min.css">
<script src="bootstrap/jquery.min.js"></script>
<script src="bootstrap/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="text-center">添加用户</h2>
<form class="form-horizontal">
<div class="form-group">
<label for="userName" class="control-label col-lg-2 col-md-offset-2">姓名:</label>
<div class="col-md-6">
<input type="text" id="userName" class="form-control" v-model="user.name" placeholder="请输入姓名"></input>
</div>
</div>
<div class="form-group">
<label for="userAge" class="control-label col-lg-2 col-md-offset-2">年龄:</label>
<div class="col-md-6">
<input type="text" id="userAge" class="form-control" v-model="user.age" placeholder="请输入年龄"></input>
</div>
</div>
<div class="form-group">
<label for="userEmail" class="control-label col-lg-2 col-md-offset-2">邮箱:</label>
<div class="col-md-6">
<input type="text" id="userEmail" class="form-control" v-model="user.email" placeholder="请输入邮箱"></input>
</div>
</div>
<div class="form-group text-center">
<input type="button" value="添加" class="btn btn-primary" @click="addUser">
<input type="reset" value="重置" class="btn btn-primary">
</div>
</form><!-- form-horizontal --> <hr>
<table class="table table-bordered table-hover" >
<caption class="h3 text-center text-info"> 用户列表</caption>
<thead>
<tr >
<th class="text-center">序号</th>
<th class="text-center">姓名</th>
<th class="text-center">年龄</th>
<th class="text-center">邮箱</th>
<th class="text-center">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(user,index) in users" class="text-center">
<td >{{index+1}} </td>
<td >{{user.name}} </td>
<td >{{user.age}} </td>
<td >{{user.email}} </td>
<td > <button class="btn btn-danger btn-sm" data-toggle="modal" data-target="#del" @click="nowIndex=index">删除</button> </td>
</tr>
<tr >
<td colspan="5" class="text-right"> <button class="btn btn-danger " data-toggle="modal" data-target="#del" @click="nowIndex=-1">删除所有</button></td>
</tr>
</tbody>
</table>
<!-- 模态框,弹出框 -->
<div class="modal fade" id="del">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button class="close" data-dismiss="modal">
<span>×</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
## 二、项目整体结构开发
vue学习记录的更多相关文章
- Vue学习记录第一篇——Vue入门基础
前面的话 Vue中文文档写得很好,界面清爽,内容翔实.但文档毕竟不是教程,文档一上来出现了大量的新概念,对于新手而言,并不友好.个人还是比较喜欢类似于<JS高级程序设计>的风格,从浅入深, ...
- Vue学习记录第一天
今天开始了Vue的学习,下面我就记录一下学习了什么. 1.什么是Vue? vue是一套基于javaScript的渐进式框架,是MVVM框架.View ——ViewModel——Model 其中Vie ...
- vue学习记录:vue引入,validator验证,数据信息,vuex数据共享
最近在学习vue,关于学习过程中所遇到的问题进行记录,包含vue引入,validator验证,数据信息,vuex数据共享,传值问题记录 1.vue 引入vue vue的大致形式如下: <temp ...
- [20190614]webpack+vue学习记录
本文记录一些学习webpack+vue相关的知识点,方便以后查阅,添加或修改 1. 初始化vue项目的代码结构 build--项目依赖包配置信息 config--项目配置文件 dev.env.js-- ...
- vue学习记录④(路由传参)
通过上篇文章对路由的工作原理有了基本的了解,现在我们一起来学习路由是如何传递参数的,也就是带参数的跳转. 带参数的跳转,一般是两种方式: ①.a标签直接跳转. ②点击按钮,触发函数跳转. 在上篇文章中 ...
- Vue学习记录第二天
又来做笔记啦,今天又自暴自弃了,还好及时清醒过来了,什么时候努力都不晚,主要是要一直坚持下去,只要坚持就一定会有收获,所有成功得人背后都是付出了巨大得努力的,没有人平白无故的成功.看似光鲜亮丽的背后, ...
- Vue学习记录-初探Vue
写在开头 2017年,部门项目太多,而且出现了一个现象,即:希望既要有APP,也能够直接扫码使用,也能放到微信公众号里面. 从技术角度来说,APP我们可以选择原生开发,也可以选择ReactNative ...
- vue学习记录(一)—— vue开发调试神器vue-devtools安装
网上有些贴子少了至关重要的一步导致我一直没装上, 切记!!install后还需build,且install和build都在vue-devtools文件夹内执行 github下载地址 点击跳转 具体步骤 ...
- Vue学习记录(二)-打包问题
由于项目需要,vue项目在build打包 之后,希望有一个类似wbeconfig的配置文件.方便判断应用所处的环境.进行相应的逻辑处理. 这边暂时记录一下思路,具体请看友情链接. 方案一:从环境变量下 ...
- vue学习记录⑤(组件通信-父与子)
今天我们看一下组件通信. 经过前面几篇文章,我们已经可以构建出完整的单个组件,并利用路由使其串联起来访问了. 但这明显还是不够的.一个页面不可能就是个单组件,一般是由多个组件合成的.正因为如此,组件之 ...
随机推荐
- linux 常用命令-ps命令
ps(process status):进程状态相关命令 1.
- beat冲刺(4/7)
目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:beta冲刺(4/7) 团队部分 后敬甲(组长) 过去两天完成了哪些任务 整理博客 ppt模板 接下来的计划 做好机动. ...
- 《TCP/IP 详解 卷1:协议》第 2 章:Internet 地址结构
第二章介绍 Internet 使用的网络层地址,即熟知的 IP 地址.连接到 Internet 的设备,基于 TCP/IP 的专用网络中使用的设备都需要一个 IP 地址. 路由器(见 IP 协议 一章 ...
- Beta阶段——3
一.提供当天站立式会议照片一张: 二. 每个人的工作 (有work item 的ID) (1) 昨天已完成的工作: 今天主要是对管理员功能进行改进,解决了Alpha阶段出现的一些问题 (2) 今天计划 ...
- httpclient的get和post
pom.xml <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId&g ...
- php反射方法信息
<?phpclass ReflectionFunction implements Reflector{ final private __clone() public object _ ...
- facenet模型训练
做下记录,脚本如下: 对比 python3 src/compare.py ../models/-/ ../faces/pyimgs/dashenlin/ytwRkvSdG1000058.png ../ ...
- HDU4183_Pahom on Water
题意为给你若干个圆,每个圆的颜色对应一个频率,如果两个圆有公共部分,那么这两个圆之间可以走,你可以从起点开始,从频率小的圆走向频率大的圆并且到达终点后,从频率大的圆走向频率小的圆,最终回到起点,路径中 ...
- MySQL 5.6 & 5.7最优配置文件模板
Inside君整理了一份最新基于MySQL 5.6和5.7的配置文件模板,基本上可以说覆盖90%的调优选项,用户只需根据自己的服务器配置稍作修改即可,如InnoDB缓冲池的大小.IO能力(innodb ...
- ionic2如何升级到最新版本、配置开发环境
好久没写东西了,去年用了angular2的RC版本和ionic2写了一个项目,因为开发周期和有些版本不稳定,所以一直没有升级,ng2新版本引用Aot打包,听说优化还不错,现在尝试升级ioni ...