Vue-one
一:vue指令:
<div id="app">
//使用v-cloak,可以解决插值表达式的闪烁问题 ,不会覆盖元素中原有的内容,只会替换自己的占位符
<p v-cloak>11111{{msg1}}9999</p>
//没有闪烁问题,但是会覆盖原有的内容
<h1 v-text="msg2"></h1>
//输出html格式,会覆盖元素中原有的内容
<h1 v-html="msg2"></h1>
//v-bind 可以简写为:,绑定属性的指令
<input type="button" value="按钮" v-bind:title="mytitle">
<input type="button" value="按钮" :title="mytitle">
//v-bind会把后面的当作js表达式执行,后面可以写合法的表达式,mytitle变量+表达式
<input type="button" value="按钮" :title="mytitle + '123'">
//v-on:click 绑定事件,相当于onclick
<input type="button" value="按钮" :title="mytitle + '123'" v-on:click="handle">
//v-on:缩写为@
<input type="button" value="按钮" :title="mytitle + '123'" @click="handle">
</div>
vue代码:
var vm = new Vue({
el: '#app',
// 数据
data: {
msg1: '哈哈哈哈',
msg2: '<h1>kkkkkk</h1>',
mytitle: 'title',
},
// 对象
methods: {
handle: function () {
alert("hello");
}
}
});
例子:跑马灯效果
html代码如下:
<div class="app2">
<input type="button" value="开始" v-on:click="handle1">
<input type="button" value="停止" v-on:click="handle2">
<h4>{{ msg }}</h4>
</div>
vue代码如下:
var vm = new Vue({
el: '.app2',
data: {
msg: '这是一个跑马灯效果',
timer: null,
},
methods: {
// 在vm实例中,要获取data的数据,或者是methods的方法,必须要this.属性名数据或this.方法名
// handle1: function () {
// // console.log(this.msg);
// var _this=this;
// setInterval(function () {
// // 获取第一个字符
// var start = _this.msg.substring(0, 1);
// // 从第一个截取到最后
// var end = _this.msg.substring(1);
// // 从新拼接,赋值给msg
// _this.msg = end + start;
// },1000)
// },
// handle2: function () {
// }
// es6写法,可以省略function,箭头函数可以指向外面的this
handle1() {
if (this.timer != null) {
return;
}
this.timer = setInterval(() => {
// 获取第一个字符
var start = this.msg.substring(0, 1);
// 从第一个截取到最后
var end = this.msg.substring(1);
// 从新拼接,赋值给msg
this.msg = end + start;
}, 1000)
},
handle2() {
clearInterval(this.timer);
this.timer = null;
}
},
})
//<!-- capture捕获事件,从外到里输出 -->
<div id="app3" @click="divHandle">
//<!-- .stop阻止冒泡 -->
<input type="button" value="点1" @click.stop="btnHandle1">
//<!-- self点击当前元素的时候才会触发当前事件 -->
<input type="button" value="点2" @click.self="btnHandle2">
//<!-- prevent阻止默认行为 -->
<a href="http://www.baidu.com" @click.prevent="linkClick">app</a>
//<!-- once只执行一次 -->
<a href="http://www.baidu.com" @click.prevent.once="linkClick">app</a>
</div>
var vm = new Vue({
el: '#app3',
data: {},
methods: {
divHandle() {alert("这是div的点击事件");},
btnHandle1() {alert("这是button的点击事件");},
btnHandle2() {alert("self");},
linkClick() {alert("Baidu");}
}
});
v-model:数据绑定
//<!-- v-model双向数据绑定,只能运用于表单元素,radio,text,address,mail,select,CheckBox -->
<div id="app1">
<h4>{{msg1}}</h4>
<input type="text" v-model:value="msg1" style="width: 500px;">
</div>
var vm = new Vue({
el: '#app1',
data: {
msg1: 'hellodfdfddkfjdfjdfjdkfdkfjdkfjkdfjd',
},
methods: {}
});
例子:使用v-model实现计算器案例
<div id="app2">
<input type="text" name="" id="" v-model="msg1">
<select v-model="opt">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" name="" id="" v-model="msg2">
<input type="button" value="=">
<input type="text" name="" id="" v-model="result">
<input type="button" value="计算" @click="calc">
</div>
var vm = new Vue({
el: '#app2',
data: {
msg1: '0',
msg2: '0',
result: '0',
opt: '-'
},
methods: {
calc() {
// 方法一
// switch (this.opt){
// case '+':this.result =parseInt(this.msg1)+parseInt(this.msg2);break ;
// case '-':this.result =parseInt(this.msg1)-parseInt(this.msg2);break ;
// case '*':this.result =parseInt(this.msg1)*parseInt(this.msg2);break ;
// case '/':this.result =parseInt(this.msg1)/parseInt(this.msg2);break ;
// }
// 方法二
var codeStr = 'parseInt(this.msg1)' + this.opt + 'parseInt(this.msg2)';
this.result = eval(codeStr);
},
}
});
vue使用样式:
<div id="app3">
<h2>第一种:数组</h2>
<h1 :class="['wraper1','wraper2','wraper3']">hkdlfjhklddhfjdfkd</h1>
<h2>第一种:在数组中使用三元表达式</h2>
<h1 :class="['wraper1','wraper2',flag?'wraper3':'']">1211111111</h1>
<h2>第一种:在数组写对象,提高可读性,flag为true就显示</h2>
<h1 :class="['wraper1',{'wraper2':flag},'wraper3']">1211111111</h1>
<h2>第一种:直接使用对象</h2>
<!-- class 使用v-bind绑定对象的属性时,由于对象的属性是类名,所以,对象的属性可带引号,可不带,属性的值是标识符 -->
<h1 :class="{wraper1:true,wraper2:false,wraper3:false}">1211111111</h1>
<!-- 把他放在属性里面 -->
<h1 :class="obj">1211111111</h1>
</div>
new Vue({
el: '#app3',
data: {
flag: true,
obj: { wraper1: true, wraper2: true, wraper3: false },
}
});
<div id="app5">
<p v-for="item in list1">{{item}}</p>
<p v-for="(item,i) in list1">索引值{{i}}+" "+{{item}}</p>
//<!-- 遍历数组 -->
<p v-for="(item,i) in list2">{{item.id}}+" "+{{item.name}}+" "+索引值{{i}}</p>
//<!-- 遍历对象 -->
<p v-for="(value,key,i) in list3">值:{{value}}+" "+键:{{key}}+" "+索引值{{i}}</p>
// <!-- 迭代数组, 如果使用数字时从1开始-->
<p v-for="count in 10">这是第{{count}}次</p>
<h1>v-for使用注意事项<h1>
id:<input type="text" v-model="id">
name:<input type="text" v-model="name">
<input type="button" value="添加" @click="add">
//<!--v-for key只能使用number或string,key使用时要用v-bind -->
//<!-- 在组件中使用v-for,或特殊情况,使用时有问题,必须指定唯一的 字符串、数字类型的key -->
<p v-for="(item,i) in list2" v-bind:key="item.id">
<input type="checkbox" name="" id="">{{item.id}}+" "+{{item.name}}</p>
</div>
new Vue({
el: '#app5',
data: {
id: '',
name: '',
list1: [1, 2, 3, 4, 5],
list2: [
{ id: 1, name: 'lisi1' },
{ id: 2, name: 'lisi2' },
{ id: 3, name: 'lisi3' },
{ id: 4, name: 'lisi4' }
],
list3: {
id: 1,
name: 'haha',
age: 12,
adddress: '中国',
}
},
methods: {
add() {
this.list2.push({ id: this.id, name: this.name })
}
}
});
v-if:
<div id="app6">
//<!-- <input type="button" value="toggle" @click="toggle"> -->
//<!-- 等于下面的 -->
<input type="button" value="toggle" @click="flag=!flag">
<h3 v-if="flag">这是v-if控制的元素</h3>
<h3 v-show="flag">这是v-show控制的元素</h3>
//<!-- v-if每一次都会重新删除和创建元素 ,有较高的切换性能消耗
如果元素频繁的切换,最好不要使用-->
//<!-- v-show每一次都不会重新删除和创建元素 ,只是切换了元素的dispaly:none样式,有较高的初始渲染消耗
如果元素可能永远也不会显示出来被用户看,推荐使用-->
</div>
new Vue({
el: '#app6',
data: {
flag: true,
},
methods: {
toggle() {
this.flag = !this.flag;
}
}
});
品牌例子:
<div id="day1">
<div class="panel panel-primary">
<div class="panel-heading">
<h1 class="panel-title">添加品牌</h1>
</div>
<div class="panel-body form-inline">
<label>
id:<input type="text" name="" id="" class="form-control" v-model="id">
</label>
<label>
//<!-- @keyup="add"是键盘抬起触发add事件 .enter键盘抬起按enter键就可以触发-->
name:<input type="text" name="" id="" class="form-control" v-model="name" @keyup.enter="add">
</label>
<label>
//<!-- v-color=('blue')是传递的值 -->
搜索关键字:<input type="text" name="" id="" class="form-control" v-model="keywords" v-focus
v-color=('blue')>
</label>
//<!-- 在vue中使用事件绑定,如果加了小括号就可以传参数add() -->
<input type="button" value="添加" class="btn btn-primary" @click="add">
</div>
</div>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>time</th>
<th>option</th>
</tr>
</thead>
<tbody>
//<!-- 自定义search()方法,通过传参的形式,传递给search方法 在这个方法中通过for循环,把符合条件的数据保存到一个新数组中返回-->
<tr v-for="item in search(keywords)" :key="item.id">
<td>{{item.id}}</td>
<td v-text="item.name"></td>
<td>{{item.time|dateFormat('')}}</td>
//<!-- 根据id删除 -->
<td><a href="" @click.prevent="del(item.id)">删除</a></td>
</tr>
</tbody>
</table>
</div>
new Vue({
el: '#day1',
data: {
id: '',
name: '',
keywords: '',
list: [
{ id: 1, name: '李四1', time: new Date() },
{ id: 2, name: '李四2', time: new Date() },
{ id: 3, name: '李四3', time: new Date() },
{ id: 4, name: '李四4', time: new Date() },
]
},
methods: {
add() {//添加方法
this.list.push({ id: this.id, name: this.name, time: new Date() })
// 添加了要清空input的数据
this.id = this.name = "";
},
del(id) {//删除
// //根据id删除
// this.list.some((item, i) => {
// if (this.id = id) {
// this.list.splice(i, 1);// 根据id查找索引,找到索引,直接调用数组splce方法删除
// // 终止后续循环
// return true;
// }
// })
// 删除方法二
var index = this.list.findIndex(item => {
if (item.id == id) {
// 终止后续循环
return true;
}
})
this.list.splice(index, 1);
console.log(index);
},
search(keywords) {//根据关键字,进行数据搜索
// var newList = [];
// this.list.forEach(item => {
// if (item.name.indexOf(keywords) != -1) {
// newList.push(item);
// }
// })
// return newList;
// 方法二
// forEach,some,filter,dindIndex都是素组的新方法
return this.list.filter(item => {
if (item.name.includes(keywords)) {
return item;
}
});
}
},
});
定义组件:
<h1>定义全局过滤器</h1>
<div class="filter">
//<!-- sgFormat('青青+1')括号里面是传递参数,可传递多个 -->
<p>{{msg|msgFormat('青青+1')}}</p>
</div>
<h1>定义私有过滤器</h1>
<div id="day3">
<h1 v-color="'green'">{{time|dateFormat}}</h1>
</div>
</div>
// 过滤器的使用
// 1、只能应用于v-bind和mustache(插值表达式{{}})
// 2、格式:{{name|nameope}}
// 3、定义全局过滤器 Vue.filter('过滤器名称',function (){})
Vue.filter('msgFormat', function (msg, arg) {
return msg.replace(/清清/g, arg)
})
new Vue({
el: '.filter',
data: {
msg: '我是我是彭清清我是我是彭清清'
},
methods: {}
})
// 定义私有过滤器
new Vue({
el: '#day3',
data: {
time: new Date(),
},
methods: {
},
// 全局指令带s,私有指令不带s
filters: {//定义私有过滤器,有两个条件:过滤器名称和处理函数,调用的时候采用就近原则,如果私有过滤器和全局过滤器的名称一致,优先调用私有
dateFormat: function (dateStr, timePattern = "") {
var time = new Date(dateStr);
var year = time.getFullYear();
// month 从0开始
var month = time.getMonth() + 1;
var day = time.getDate();
if (timePattern.toLowerCase() == 'yyyy-mm-dd') {
return `${year}-${month}-${day}`;
} else {
var hour = time.getHours();
var minutes = time.getMinutes();
var seconds = time.getSeconds();
return `${year}-${month}-${day} ${hour}:${minutes}:${seconds}----`;
}
}
},
})
Vue.config.keyCodes.f2 = 113;//自定义按键修饰符
Vue.directive('focus', {// 自定义全局指令获取焦点 注意:参数1:指令名称 :定义的时候不需要加v-前缀,调用的时候必须加v-
// 参数2:是一个对象,
bind: function (el) {//每当指令绑定到元素上的时候,会执行这个函数
// 在每一个函数中,第一个参数永远是el,表示被绑定指令的元素,这个元素是原始的js对象
},
inserted: function (el) {//插入到DOM的时候,执行这个函数
el.focus()
},
updated: function () {//每当vNode更新的时候执行
}
})
Vue.directive('color', {//自定义全局设置字体颜色的指令}
bind: function (el, binding) {
//el.style.color = 'red'//样式只要通过指令不绑定给了元素,不管有没有插入到页面中,这个元素肯定有了内联样式
el.style.color = binding.value;
}
// 和样式相关的在bind设置就可以,和行为相关的在inserted设置,防止js行为不生效
})
// 定义全局格式化时间
Vue.filter('dateFormat', function (dateStr, timePattern = "") {
var time = new Date(dateStr);
var year = time.getFullYear();
// month 从0开始
var month = time.getMonth() + 1;
var day = time.getDate();
// 如果传递timePattern参数不等于yyyy-mm-dd,就把他转化为小写,如果是yyyy-mm-dd格式的
// 说明显示的是年月日否则就是完整的时间
if (timePattern.toLowerCase() == 'yyyy-mm-dd') {
return `${year}-${month}-${day}`;
} else {
var hour = time.getHours();
var minutes = time.getMinutes();
var seconds = time.getSeconds();
return `${year}-${month}-${day} ${hour}:${minutes}:${seconds}`;
}
})
定义私有指令:指令名称是驼峰命名的,由于html不认识驼峰命名,所以引用的时候用-连接起来
html代码如下:
<div id="day3">
<h1 v-font-Style="'italic'" v-font-Size="30">{{time|dateFormat}}</h1>
</div>
vue代码如下:
new Vue({
el: '#day3',
data: {
time: new Date(),
},
methods: {
},
// 全局指令带s,私有指令不带s
filters: {//定义私有时间过滤器,有两个条件:过滤器名称和处理函数,调用的时候采用就近原则,如果私有过滤器和全局过滤器的名称一致,优先调用私有
dateFormat: function (dateStr, timePattern = "") {
var time = new Date(dateStr);
var year = time.getFullYear();
// month 从0开始
var month = time.getMonth() + 1;
var day = time.getDate();
if (timePattern.toLowerCase() == 'yyyy-mm-dd') {
return `${year}-${month}-${day}`;
} else {
var hour = time.getHours();
var minutes = time.getMinutes();
var seconds = time.getSeconds();
return `${year}-${month}-${day} ${hour}:${minutes}:${seconds}----`;
}
}
},
directives: {//定义私有指令
'fontStyle': {
bind: function (el, binding) {
el.style.fontStyle = binding.value;
}
},
'fontSize': function (el, binding) {//这个函数等同于把代码写到了bind和update中
el.style.fontSize = parseInt(binding.value) + 'px';
}
}
});
vue动画:
(1)、使用过渡类名定义动画
HTML代码如下:
<div id="app">
<input type="button" value="toggle" @click="show=!show">
//<!-- 使用transition把需要动画的元素包裹起来 这是vue官方提供的-->
<transition name="my">
// <!--使用name属性来定义前缀来自定义动画,使用的时候.my-enter-->
//<!-- 点击按钮让小圆展示出来,v-show 和v-if都行-->
<h3 class="circle" v-show="show">这是一个动画</h3>
</transition>
</div>
样式代码如下:
//* 自定义两组样式,来控制transition内部的元素实现动画 */
.my-enter,
//*这是一个时间点,是进入之前元素的起始状态,此时还没有开始进入*/
v-leave-to {
//*这是一个时间点,是离开之后,离开的终止状态,此时动画已结束*/
opacity: 0;
transform: translateX(150px);
}
.my-enter-active,
/ /*入场动画的时间段*/
.my-leave-active {
/ /*离场动画的时间段*/
transition: all 1s ease;
}
vue代码如下:
new Vue({
el: '#app',
data: {
show: false
},
methods: {},
});
(2)、使用第三方css类库定义动画
<div id="app">
<input type="button" value="toggle" @click="show=!show">
//<!-- :duration="400"统一设置动画的出场,和入场动画时长 -->
//<!-- :duration="{enter:200,leave:400} 分别设置动画的出场,和入场动画时长-->
<transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut" :duration="400">
<h3 class="circle" v-show="show">这是一个动画</h3>
</transition>
//<!-- 把animated放在元素上 -->
<transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="{enter:200,leave:400}">
<h3 class="circle" v-show="show" class="animated">这是一个动画</h3>
</transition>
</div>
(3) 、钩子函数实现半场动画(只需要进入动画或是只需要出场动画)
例子:小球动画
HTML 代码如下:
<div id="app">
<input type="button" value="toggle" @click="show=!show">
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<h3 class="circle" v-show="show"></h3>
</transition>
</div>
样式代码如下:
.circle {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: olive;
}
vue代码如下:
new Vue({
el: '#app',
data: {
show: false
},
methods: {
//动画钩子函数的第一个参数是el,不是要执行动画的DOM元素,是原生的jsDOM对象,可以认为是通过document.getElementById获取到的
beforeEnter(el) {//这个函数是表示,动画入场前,此时动画未开始,在这里设置动画之前的起始样式
el.style.transform = "translate(0,0)"//设置小球开始前的动画
},
enter(el,done) {//这个函数是表示,动画开始之后的样式,可以设置小球完成后的结束状态
el.offsetWidth;//这句话没有实际应用,强制动画刷新,不设置动画就不会出来,有height,left,top
el.style.transform = "translate(150px,150px)";
el.style.transition = "all 1s ease";
done();//这个是afterEnter函数的引用,加上会停留一会在消失,不然就会立即消失
},
afterEnter(el) {//这个函数是表示,动画完成之后
this.show=!this.show;
}
},
});
(4)、使用transition-group实现列表组动画
HTML代码如下:
<div id="app">
<div>
<label>Id:<input type="text" v-model="id"></label>
<label>Name:<input type="text" v-model="name"></label>
<input type="button" value="添加" @click="add">
</div>
//<!-- <ul> -->
// <!-- 实现列表过渡的时候,如果过渡的元素是v-for循环渲染的,不能使用transition包裹,使用transition-group -->
//<!-- 如果用v-for循环创建动画,必须为每一个元素设置:key属性 -->
<transition-group appear tag="ul">
//<!--给transition-group添加appear属性,给页面刚展示出来入场效果-->
<li v-for="item in list" :key="item.id" @click="del">
{{item.id}}---{{item.name}}
</li>
</transition-group>
//<!-- 由于transition-group默认会渲染为span元素,span里面包含li是不符合w3c规范,所以要设置tag属性为ul-->
//<!-- </ul> -->
</div>
样式代码如下:
li { list-style: none; border: orange 1px solid; margin-right: 5px; line-height: 30px; font-size: 12px; width: 100%; } //* 进入动画 */ .v-enter, .v-leave-to { opacity: 0; transform: translateX(15px); } .v-enter-active, .v-leave-active { transition: all 1s ease; } li:hover { background-color: olivedrab; transition: all 0.4s ease; } //* 离开动画 .v-move/v-leave和.v-leave配合使用*/ .v-move { /*v-leave也行*/ transition: all 1s ease; } .v-leave-active { position: absolute; }
vue代码如下:
new Vue({
el: '#app',
data: {
id: '',
name: '',
list: [
{ id: 1, name: '李四1' },
{ id: 2, name: '李四2' },
{ id: 3, name: '李四3' },
{ id: 4, name: '李四4' },
]
},
methods: {
add() {
console.log("a");
this.list.push({ id: this.id, name: this.name })
},
del(i) {//删除
this.list.splice(i, 1);
}
},
});
vue组件化和模块化:
什么是组件组建是为了拆分实例的代码量,能够让我们以不同的主见来划分不同的功能模块,将来我们需要什么样的功能就可以去调用对应的组件
组件化和模块化的不同:
模块化是从代码逻辑的角度进行划分的,方便代码分量开发,保证每个功能模块的职能单一
组件化是从ui界面的角度进行划分的,前端的组件转变,uI组件的重用
(1)、分别使用Vue.extend和Vue.component创建组件
<div id="app">
//<!-- 如果要使用组件,直接把组件的名称以HTML标签形式引入到页面中 -->
<my-Com1></my-Com1>
</div>
// 1、使用Vue.extend创建的全局组件
var com1 =Vue.extend({
template:'<h3>这是使用Vue.extend创建的全局组件</h3>'//通过template属性指定组件要展示的HTML结构
});
// 2、Vue.component('组件名称',创建出来的组件模块对象)
Vue.component('myCom1',com1)//注意:组件名称是驼峰命名法,引用的时候两个单词之间要使用—连接
// 创建vue实例
new Vue({
el:'#app',
data:{}
});
(2)、使用对象字面量的形式创建
// Vue.component第一个参数:组件名称,将来引入的时候就使用标签的形式引入,第二个参数:Vue.extend创建的组件,其中template属性就是组件要展示的HTML内容
Vue.component('myCom1',Vue.extend({
template:'<h3>这是使用Vue.extend创建的全局组件</h3>'
}));
// 上面的方式还可以简化,使用对象字面量的形式创建
Vue.component('myCom1',{
// 注意:无论使用哪种方式创建组件,属性template指定的模板内容有且只有唯一一个根元素,要用div包裹起来
template:'<div><h3>这是使用Vue.extend创建的全局组件<span>123</span></h3></div>'
});
// 创建vue实例
new Vue({
el:'#app',
data:{}
});
(3)、把模板template单独的抽取出去
<body>
<div id="app">
<my-Com1></my-Com1>
</div>
//<!-- 在被控制的#app外面,使用template元素,定义组件HTML结构 -->
<template id="com1">
<div>
<h3>这是通过template元素,在外部定义的组件结构,这个方式有代码提示</h3>
</div>
</template>
</body>
</html>
<script>
Vue.component('myCom1', {
template: '#com1'
});
// 创建vue实例
new Vue({
el: '#app',
data: {}
});
</script>
以上都是全局的
(4)、使用components创建私有组件
<div id="app"> <login></login> </div>
// 创建vue实例 new Vue({ el: '#app', data: {}, methods: {}, components:{ login:{ template:'<h3>这是通过template元素</h3>' } } });
(5)、组件中的data:组件中可以有自己的data,但和实力中的data不一样,组件中的data要为一个函数,并且返回的是一个对象,但使用方式是一样的
Vue.component('myCom1', {
template: '<h3>这是全局组件--{{msg}}</h3>',
data:function (){
return {
msg:'这是组件中定义的data数据'
};
}
});
(6)、为什么组件的data要为一个function,下面用实例演示
<div id="app">
<my-Com1></my-Com1>
<my-Com1></my-Com1>
<my-Com1></my-Com1>
</div>
<template id="day">
<div>
<input type="button" value="+1" @click="add">
<h3>{{count}}</h3>
</div>
</template>
// var dataObject={count: 0};
Vue.component('myCom1', {
template: '#day',
data: function () {
return {
count: 0
// dataObject//如果把对象定义在外面,当调用多次组件的时候,点击一个按钮其他按钮会受到影响
};
},
methods: {
add() {
this.count++;
}
},
});
// 创建vue实例
new Vue({
el: '#app',
data: {},
methods: {},
});
组件的切换:
(1)、v-if和v-else实现很多组件的切换,缺点是:只能切换两个,当有多个的时候就不行
<div id="app">
<a href="" @click.prevent="show=true">登入</a>
<a href="" @click.prevent="show=false">注册</a>
<login v-if="show"></login>
<register v-else="show"></register>
</div>
Vue.component('login', {
template: '<h3>登入组件</h3>',
});
Vue.component('register', {
template: '<h3>注册组件</h3>',
});
// 创建vue实例
new Vue({
el: '#app',
data: {
show:true
},
methods: {},
});
(2)、使用component切换多个组件
<div id="app">
<a href="" @click.prevent="comName='login'">登入</a>
<a href="" @click.prevent="comName='register'">注册</a>
//<!-- vue提供的component来展示对应名称的组件,component是一个占位符,is属性指定要展示的组件的名称 -->
<component :is="comName"></component>
// <!-- 属性绑定会把后面的当作表达式解析 -->
</div>
// 组件名称是字符串,:is属性绑定会把后面的当作表达式解析,并不是真正的字符串,所以'login'要用单引号包起来
Vue.component('login', {
template: '<h3>登入组件</h3>',
});
Vue.component('register', {
template: '<h3>注册组件</h3>',
});
// 创建vue实例
new Vue({
el: '#app',
data: {
comName:'login'//这个comName是 :is属性绑定的组件名称,默认展示login
},
methods: {},
});
(3)、组件切换应用动画
<div id="app">
<a href="" @click.prevent="comName='login'">登入</a>
<a href="" @click.prevent="comName='register'">注册</a>
//<!-- mode属性:设置组件切换的模式,out-in是上一个消失了才消失下一个 -->
<transition mode="out-in">
<component :is="comName"></component>
</transition>
</div>
/* 进入动画 */
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(15px);
}
//出场动画
.v-enter-active,
.v-leave-active {
transition: all 1s ease;
}
父组件和子组件传递值的data和props区别
// 子组件,默认无法访问到副总监的data上的数据和methods中的方法,副组件可以在引用纸组件的时候,通过绑定v-bind的形式,
// 把需要传递给子组件的数据以属性绑定的形式传递到子组件的内部,供子组件使用
Vue.component('com1', Vue.extend({
template:'<h1>hekk</h1>'
}))
new Vue({
el: '#app',
// data上的数据都是可读可写的
data: {//注意:子组件的data数据,不是通过父组件传递过来的,而是子组件自身有的,如:子组件通过ajax,请求回来的数据,都可以在data上定义
msg:'这是父组件中的数据'
},
methods: {},
components:{
com1:{
template:'<h1 >这是子组件---{{parentmsg}}</h1>',
// 注意:组件中的所有props中的数据都是通过父组件传递给子组件的
// props中的数据是只读的,无法重新复制被修改
props:['parentmsg']//把父组件传递过来的parentmsg属性,先在props数组中定义一下,才能使用
}
}
});
子组件通过事件调用向父组件传值
var com1 = {
template: '#com',
data() {
return {
sonmsg: { name: "李四", age: 13 }
}
},
methods: {
// 子组件的点击事件
myclick() {
// $emit 英文意思是触发,发射
this.$emit('func', this.sonmsg)//调用父组件的方法并传递参数,this.sonmsg传递给父组件
},
},
}
new Vue({
el: '#app',
data: {
datamsg:null
},
methods: {
show(data) {
console.log("调用了父组件的方法");
this.datamsg=data;
}
},
components: {
com1
}
});
使用ref获取dom元素和组件引用
<!-- 使用ref获取dom元素和组件引用 -->
<div id="app">
<input type="button" value="获取元素" @click="getElement">
<h3 id="myh3" ref="myh3">haha</h3>
<login ref="loginref"></login>
</div>
</body>
//上面是HTML
<script>
var login = {
template: '<h3>login</h3>',
data() {
return {
msg: 'sonmsg'
}
},
methods: {
show() {
console.log('调用了子组件的方法')
}
},
}
new Vue({
el: '#app',
data: {},
methods: {
getElement() {
// console.log(document.getElementById('myh3').innerHTML);
// console.log(this.$refs.myh3.innerText);//ref是reference的缩写
console.log(this.$refs.loginref.msg);//用ref输出组件的信息
this.$refs.loginref.show();//调用组的方法
}
},
components: {
login
}
});
vue路由
后端路:由对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源
前端路由:对于当页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时hash有一个特点,HTTP请求中不会包含hash相关的内容,所以当页面跳转主要用hash实现,在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由
(1)、router-link、router动画、路由高亮使用
HTML代码:
<div id="app">
//<!-- <a href="#/login">登入</a> -->
//<!-- <a href="#/register">注册</a> -->
//<!-- router-link默认渲染的是a标签,用router-link就不用加# -->
<router-link to="/login" tag="span">登入</router-link>
//<!--tag="span"渲染为span标签-->
<router-link to="/register">注册</router-link>
//<!-- router-view是vue-router提供的元素,用来当占位符,路由规则匹配到的组件展示在这里 -->
//<!-- 给路由加动画 -->
<transition mode="out-in">
<router-view></router-view>
</transition>
</div>
样式代码:
//* 设置当前展示的样式,路由高亮(路由默认的,自带的) */
.router-link-active {
color: olive;
font-weight: 500;
text-decoration: underline;
font-size: 30px;
}
//* 自定义的路由高亮 */
.myactive {
color: olive;
font-weight: 500;
text-decoration: underline;
font-size: 30px;
}
//* 路由动画 */
.v-enter,
.v-leave-to{
opacity: 0;
transform: rotateX(140px);
}
.v-enter-active,
.v-leave-active{
transition: all 1s ease;
}
vue代码:
var login = {
template: '<h1>login</h1>'
}
var register = {
template: '<h1>register</h1>'
}
// 创建一个路由对象,当导入vue-router包之后,在windows全局对象中就有了一个路由的构造函数叫做VueRouter
var routerObj = new VueRouter({//new 一个路由对象,可以为一个构造函数,传递一个配置对象
//
routes: [//这个配置对象的routes表示:路由匹配规则,
// 每个匹配规则有两个属性,一:path,表示监听哪个路由链接地址
// 二:component表示,如果路由是前面匹配到的path,则表示component属性对应的哪个组件
// 注意:component属性值必须是一个组件对象,不能是组件的引用名称
{ path: '/', redirect: '/login' },//手动修改hash值
{ path: '/login', component: login },
{ path: '/register', component: register },
],
linkActiveClass: 'myactive'//自定义自己的高亮样式
})
new Vue({
el: '#app',
data: {},
methods: {},
router: routerObj//将路由规则对象注册到我们的vm实例上,然后展示对应的组件
});
(2)、路由规则中定义参数
2.1、使用query方式传递参数
<div id="app">
//<!-- 如果在路由中使用查询字符串,给路由传递参数则不需要修改路由规则的path属性,就是 { path: '/', redirect: '/login' }, -->
//<!-- to="/login?id=10&&name=李思",传递参数,可以传递多个 -->
<router-link to="/login?id=10&name=李思">登入</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>
var login = {
template: '<h1>login---{{$route.query.id}}---{{$route.query.name}}</h1>',//this可以省略
data(){
return{
msg:'124'
}
},
created() {// 组件生命周期钩子函数
console.log(this.$route);//$route和$ref差不多
console.log(this.$route.query.id);//输出id里面的值。
},
}
var register = {
template: '<h1>register</h1>'
}
var routerObj = new VueRouter({
routes: [
{ path: '/login', component: login },
{ path: '/register', component: register },
],
});
new Vue({
el: '#app',
data: {},
methods: {},
router: routerObj,//属性名和属性值一样可以简化,就是new出来的router的名称和router一样只用写一个,现在这个router: routerObj不一样
});
2.2、使用params方式传递路由参数
<div id="app">
//<!-- 使用params传递参数 -->
<router-link to="/login/10/lisi">登入</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>
<script>
var login = {
template: '<h1>login---{{$route.params.id}}--{{$route.params.name}}</h1>',//this可以省略
data(){
return{
msg:'124'
}
},
created() {// 组件生命周期钩子函数
console.log(this.$route.params.id);
},
}
var register = {
template: '<h1>register</h1>'
}
var routerObj = new VueRouter({
routes: [
{ path: '/login/:id/:name', component: login },//:id解析id,:name解析name,通过URL地址,可以有多个参数
{ path: '/register', component: register },
],
});
new Vue({
el: '#app',
data: {},
methods: {},
router: routerObj,//属性名和属性值一样可以简化,就是new出来的router的名称和router一样只用写一个,现在这个router: routerObj不一样
});
使用children实现路由嵌套
HTML代码如下:
<body>
<div id="app">
<router-link to="/account">account</router-link>
<router-view></router-view>
</div>
<template id="com">
<div>
<h1>这是Account组件</h1>
<router-link to="/account/login">登入</router-link>
<router-link to="/account/register">注册</router-link>
<router-view></router-view>
</div>
</template>
</body>
vue代码如下:
<script>
var account = {
template: '#com',
}
var login = {
template: '<h3>登入</h3>',
}
var register = {
template: '<h3>注册</h3>',
}
var router = new VueRouter({
routes: [
{ path: '/account',
component: account ,
children:[
{path: 'login', component: login },//使用children属性前面,不带/,否则永远以跟路劲请求,不方便用户理解URL地址
{path: 'register', component: register },
]
},
// { path: '/account/login', component: login },
// { path: '/account/register', component: register },
]
})
new Vue({
el: '#app',
router//属性名和属性值一样可以简化,就是new出来的router的名称和router一样只用写一个
});