Vue.js教程
https://www.runoob.com/try/try.php?filename=vue2-hw
在线编辑器
一、Vue 最火的前端框架 Angular.js React.js最流行,可以用于手机app开发,三大框架; 关注视图层;
1)提升开发效率;js=>Jquery=>前端模板引擎=>框架帮助减少不必要的DOM操作,通过双向数据绑定;
2)框架和库的区别:
框架提供完整的解决方案;项目开发后不易切换
库只是单一的小功能,插件;容易切换;
3)Vue结构
<div id='app'>
<p>{{ msg}}</p>
</div>
<script>
vm = new Vue(){
el:'#app'
data:{
msg:"123"
}
}
</script>
二、1)、Vue指令;
[v-cloak]可以解决插值闪烁的问题;可以前后添加字符串,
[v-text]默认无闪烁问题;会覆盖元素中原有的内容
[v-text]可以渲染html数据,会覆盖元素中原有的内容
v-bind 用于绑定属性的指令;可以js运算 v-bind:title=
v-bind可以简写为:要绑定的属性;
v-on:用来绑定事件: v-on:click="show"
v-on:mouseover= 浏览器操作都可以定义;
可以缩写: @clcik=show
2)、文字走马灯:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.bootcss.com/vue/2.4.0/vue.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
<div id="app">
<input type="button" value = "run" @click = "run">
<input type="button" value = "stop" @click = "stop">
<h2>{{ msg }}</h2>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: '勤劳勇敢的中国人,加油!!',
intervalId:null
},
methods:{
run(){
<!-- var _this = this
setInterval(function(){
//console.log(this.msg)
var start= _this.msg.substring(0,1) //获取首字符
var end = _this.msg.substring(1) //获取1到结尾的字符
_this.msg = end + start
},400)//原始写法
-->
if(this.intervalId !=null) return;
this.intervalId =setInterval(()=>{ //箭头函数简写法,外部指向和内部指向一致
var start= this.msg.substring(0,1) //获取首字符
var end = this.msg.substring(1) //获取1到结尾的字符
this.msg = end + start
},400)
},
stop(){
clearInterval(this.intervalId)
this.intervalId = null;//停止后赋值开关状态
}
}
})
</script>
</body>
</html>
三、事件修饰符
1、.stop 阻止后续所有元素冒泡;
2、.prevent 阻止默认事件行为
3、 .capture 捕获触发事件机制(从外到里执行事件)
4、 .self 只有点击当前元素自身才触发事件
4、 .once 只触发一次事件
四、v-model 双向数据绑定
1、v-model 可以实现表单的双向绑定
<body>
<div id="app">
<h4>{{msg}}</h4>
<!-- <input type = "text" v-bind:value= "msg" style="width:100%;"> v-bind 只能单向绑定 M->V -->
<input type = "text" v-model:value= "msg" style="width:100%;"> <!--v-model 可以实现表单的双向绑定 M->V -->
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: '勤劳勇敢的中国人,加油!!',
},
methods:{
}
});
</script>
</body>
--------------------------------
2、简易计算器案例
五、Vue中使用样式:
1、数组中绑定,直接传值;
<style>
.thin{
font-weight: 200;
}
.italic{
font-style:italic;
}
.red{
color: red;
}
.active{
letter-spacing: 0.5em;
}
</style>
<body>
<h1 :class="['thin','ltalic','active']">
</body>
2、数组中使用三元表达式
<h1 :class="['thin','ltalic',flag?'active':'']">
<script>
var vm = new Vue({
el: '#app',
data: {
flag:true //false
},
methods:{
}
});
</script>
3、在数组中使用三元表达式,可读性更强;
<h1 :class="['thin','ltalic',{'active':flag}]">
4、直接使用对象
<h1 :class= stylobj"{red:true,this:true,italic:false,active:false}">
或:
<h1 :class= "stylobj" ></h1>
<script>
var vm = new Vue({
el: '#app',
data: {
stylobj:{
red:true,
this:true,
italic:false,
active:false}
}
},
methods:{
}
});
</script>
5、通过属性绑定为元素绑定为元素绑定style行内样式
<h1 :style="{color:'red'},'font-weight':200}">
或者
<h1 :class= "stylobj" ></h1>
<script>
var vm = new Vue({
el: '#app',
data: {
stylobj:{ color:'red','font-weight':200 }
},
methods:{
}
});
</script>
六、v-for循环指令 :for循环
(一)普通数组:
1、方式1:
<body>
<div id="app">
<p v-for = "item in list">{{item}}</p>
<input type="button" value = "stop" @click = "cl">
</div>
<script>
var vm =new Vue({
el:'#app',
data: {
list: [1,2,3,4,5,6]
},
methods: {
cl(){alert('hehe')
}
}
});
</script>
2、方式2
<script src="https://cdn.bootcss.com/vue/2.4.0/vue.js"></script>
</head>
<body>
<div id="app">
<p v-for = "(item,i) in list">索引值:{{i}}<
===>每一项:{{item}}</p>
<input type="button" value = "stop" @click = "cl">
</div>
<script>
var vm =new Vue({
el:'#app',
data: {
list: [1,2,3,4,5,6]
},
methods: {
cl(){alert('hehe')
}
}
});
</script>
</body>
(二)、循环对象数组:
<body>
<div id="app">
<!-- <p v-for = "user in list">Id:{{user.id}}
…………姓名:{{user.name}}</p>-->
<p v-for = "(user,i) in list">Id:{{user.id}}
…………姓名:{{user.name}}---index:{{i}}</p>
<input type="button" value = "stop" @click = "cl">
</div>
<script>
var vm =new Vue({
el:'#app',
data: {
list: [
{id:01,name:'张三'},
{id:02,name:'lisi'},
{id:03,name:'王五'},
{id:04,name:'赵六'},
{id:05,name:'陈七'}
]
},
methods: {
cl(){alert('hehe')
}
}
});
</script>
</body>
(三)、循环对象
<body>
<div id="app">
<p v-for = "(val,key,i) in user">Index:{{i}}---Value:{{val}}
…………Key:{{key}}---</p>
<input type="button" value = "stop" @click = "cl">
</div>
<script>
var vm =new Vue({
el:'#app',
data: {
user:{
id:1,
name: 'tom moby',
gender:'男'
}
},
methods: {
cl(){alert('hehe')
}
}
});
</script>
</body>
(四)、数字迭代
<body>
<div id="app">
<p v-for = "item in 10">第{{item}}项 <!--从1开始-->
</p>
(五)、v-for循环中key属性的使用
<body>
<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>
<p v-for = "item in list" :key="item.id">
<input type="checkbox" >{{item.id}}----{{item.name}}
</p>
</div>
<script>
var vm =new Vue({
el:'#app',
data: {
id:'',
name:'',
list:[
{id:1,name:'张飞'},
{id:2,name:'关羽'},
{id:3,name:'鲁肃'},
{id:4,name:'周瑜'},
{id:5,name:'张辽'}
]
},
methods: {
add(){
//this.list.push({id:this.id, name: this.name})
this.list.unshift({id:this.id, name: this.name})
}
}
});
</script>
</body>
——————————
v-for循环的时候,key属性只能使用number提取string
key在使用的时候,必须使用v-bind属性绑定的形式,指定key的值
在组件中,使用v-for循环的时候,或者特殊情况中,如果v-for有问题,必须在使用v-for时,指定唯一的字符串/数字 类型 :key 值
七、v-if
(一):
<body>
<div id="app">
<!-- <input type="button" value="toggle" @click="toggle"> -->
<input type="button" value="toggle" @click="flag=!flag"> <!-- 简写-->
<p v-if="flag">this is controlled by v-if<p>
<p v-show="flag">this is controlled by v-SHOW</p>
</div>
<script>
new Vue({
el: '#app',
data: {
flag: true
},
methods:{
toggle(){
this.flag =!this.flag
}
}
});
</script>
</body>
v-if 特点:删除或创建元素,较高的性能消耗
v-show 特点:不删除或创建元素;只是切换了dispaly:none dispaly:show 较高的初始性能消耗;切换频繁宜用这个。
(二)、案例:品牌添加删除
<body>
<div id="app">
<div class= "panel panel-primary">
<div class= "panel-heading">
<h3 class="panel-title">添加品牌</h3>
</div>
<div class= "panel-body form-inline">
<label>
Id:
<input type="text" class="form-control" v-model="id">
</label>
<label>
Name:
<input type="text" class="form-control" v-model="name">
</label>
<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>Ctime</th>
<th>Opertation</th>
</tr>
</thead>
<tbody>
<tr v-for = "item in list" :key="item.id">
<td>{{ item.id }}</td>
<td v-text="item.name"> </td>
<td>{{ item.ctime }}</td>
<td>
<a href="" @click.prevent="del(item.id)" >删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script>
new Vue({
el: '#app',
data: {
id:'',
name:'',
list:[
{id:1,name:'奔驰',ctime:new Date()},
{id:2,name:'宝马',ctime:new Date()},
{id:3,name:'卡迪拉克',ctime:new Date()}
]
},
methods:{
add(){
var car= {id: this.id,name:this.name,ctime: new Date()}
this.list.push(car)
this.id = ''
this.name= ''
},
del(id){
/* this.list.some((item,i)=>{ //方法1
if(item.id == id){
this.list.splice(i,1)
return true;
}
}) */
var index =this.list.findIndex(item=>{//方法2
if(item.id == id){
return true;
}
})
this.list.splice(index,1)
}
}
});
</script>
</body>
(二)过滤器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 品牌列表(runoob.com)</title>
<script src="https://cdn.bootcss.com/vue/2.4.0/vue.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div id="app">
<div class= "panel panel-primary">
<div class= "panel-heading">
<h3 class="panel-title">添加品牌</h3>
</div>
<div class= "panel-body form-inline">
<label>
Id:
<input type="text" class="form-control" v-model="id">
</label>
<label>
Name:
<input type="text" class="form-control" v-model="name">
</label>
<input type="button" value="添加" class="btn btn-primary" @click="add" >
<label>
搜索:
<input type="text" class="form-control" v-model="keywords">
</label>
</div>
</div>
<table class="table table-bordered table-hover table-striped" >
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Ctime</th>
<th>Opertation</th>
</tr>
</thead>
<tbody>
<!-- <tr v-for = "item in list" :key="item.id"> 仅能列表-->
<tr v-for = "item in search(keywords)" :key="item.id">
<td>{{ item.id }}</td>
<td v-text="item.name"> </td>
<td>{{ item.ctime | dateFormat('')}}</td> <!-- dateFormat('yyyy-mm-dd')-->
<td>
<a href="" @click.prevent="del(item.id)" >删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script>
Vue.filter('dateFormat',function(dateStr,pattern=""){ //第二参数决定时间格式
var dt=new Date(dateStr)
var y = dt.getFullYear()
var m = dt.getMonth() + 1
var d = dt.getDate()
if(pattern && pattern.toLowerCase() === 'yyyy-mm-dd'){
return `${y}-${m}-${d}` //` ~的同位键 非' 构成魔法字符串
}else{
var hh = dt.getHours()
var mm = dt.getMinutes()
var ss = dt.getSeconds()
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
}) //全局过滤器 :所有实例都可以共享
new Vue({
el: '#app',
data: {
id:'',
name:'',
keywords:'',
list:[
{id:1,name:'奔驰',ctime:new Date()},
{id:2,name:'宝马',ctime:new Date()},
{id:3,name:'卡迪拉克',ctime:new Date()},
]
},
methods:{
add(){
var car= {id: this.id,name:this.name,ctime: new Date()}
this.list.push(car)
this.id = ''
this.name= ''
},
del(id){
/* this.list.some((item,i)=>{ //方法1
if(item.id == id){
this.list.splice(i,1)
return true;
}
}) */
var index =this.list.findIndex(item=>{//方法2
if(item.id == id){
return true;
}
})
this.list.splice(index,1)
},
search(keywords){
/*var newList = []
this.list.forEach(item=>{
if(item.name.indexOf(keywords) != -1){
newList.push(item)
}
})
return newList
*/
returnthis.list.filter(item =>{
if(item.name.includes(keywords)){
return item
}
})
}
},
//私有过滤器 过滤器:名称 处理函数 通道符调用时先局部后全局
filters:{
dateFormat: function(dateStr,pattern=""){
var dt=new Date(dateStr)
var y = dt.getFullYear()
var m = dt.getMonth() + 1
var d = dt.getDate()
if(pattern && pattern.toLowerCase() === 'yyyy-mm-dd'){
return `${y}-${m}-${d}` //` ~的同位键 非' 构成魔法字符串
}else{
var hh = dt.getHours()
var mm = dt.getMinutes()
var ss = dt.getSeconds()
return `${y}-${m}-${d} ${hh}:${mm}:${ss}~`
}
}
}
});
</script>
</body>
</html>
(三)padStart(2,'0') //用0补足数位到2位 padEnd
.toString().padStart(2,'0')
(四)绑定键盘事件
<input type="text" class="form-control" v-model="name" @keyup.enter="add" >
内置监听键 .enter
.tab
.delete
.esc
.space
.up .down .left .right
其他按键,可以用码值, 如f2==> 113
<input type="text" class="form-control" v-model="name" @keyup.e113="add" >
自定义全局装饰符,还可以自定义 码值和键对应
Vue.config.keyCodes.f4 = 115
(五).focus
document.getElementById('search').focus(); 原生方法不建议使用
自定义指令
Vue.directive() //参数1:指令名称,无需v-,调用必需v-;参数2:对象,有一些指令相关的钩子函数:bind inserted update componentUpdated unbind
<input type="text" class="form-control" v-model="keywords" v-focus v-color>
<script>
Vue.directive('color',{
inserted:function(el){
el.focus()
//和js行为相关的操作一般在inserted中执行
}
})
Vue.directive('color',{
bind:function(el){
el.style.color = 'red'
},
})
//和样式相关的操作一般在bind中执行
</script>
-----------------------------
自定义指令,颜色传参
<input type="text" class="form-control" v-model="keywords" v-focus v-color ="'blue'">
Vue.directive('color',{
bind:function(el,binding){
el.style.color = binding.value
},
})
----------------------------------------------------
(六)私有指令 v-fontsize v-fontweight调用
directives: { //自定义私有指令
'fontweight':{
bind: function (el,binding){ //binding接受参数
el.style.fontWeight = binding.value
}
},
'fontsize': function(el,binding) { //简写方式
el.style.fontSize = parseInt(binding.value) + 'px'
}
}
七、vue实例的生命周期:
生命周期钩子=生命周期函数=生命周期事件
//创建一个vue实例对象
var vm=new Vue({
el:'#app',
data: {
msg: 'ok',
},
methodes: {
},
beforeCreate() { //第一个生命周期函数
},
created() { //第二个生命周期函数
},
//下为第三个生命周期函数
beforeMount() { //模板已经在内存中编译完成,尚未把模板渲染到页面中
},
//下为第四个生命周期函数
mounted() { //把编译好的模板放到页面中,用户可以看到最终页面
}, //是实例创建期间最后一个生命周期函数,执行完后。实例已经完全创建好了。如无其他函数,这个实例则静静存储在内存中
如要操作dom节点,应该在mounted中操作。执行完mounted,创建阶段已经结束,进入到运行阶段beforeUpdate() update()
beforeUpdate(){
}, //执行时,页面中显示的内容还是旧的,data数据是最新的,页面尚未和最新的数据同步
updated(){
}, //此事件执行时,date和页面中的数据已经同步了
beforeDestroy(){
}, //执行此函数时未真正销毁
destroyed){
}, //执行此函数时真正销毁
})
(八)、vue-resouce ,axios第三方包实现get、 post、 json请求
<!DOCTYPE html>
<meta http-equiv="Access-Control-Allow-Origin" content="*" />
<html lang="en">
<head>
<meta charset="utf-8">
<title>Vue 品牌列表(runoob.com)</title>
<script src="https://cdn.bootcss.com/vue/2.4.0/vue.js"></script>
<script src="https://cdn.bootcss.com/vue-resource/1.3.4/vue-resource.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div id="app">
<div class= "panel panel-primary">
<div class= "panel-heading">
<h3 class="panel-title">添加品牌</h3>
</div>
<div class= "panel-body form-inline">
<label>
Id:
<input type="text" class="form-control" v-model="id">
</label>
<label>
Name:
<input type="text" class="form-control" v-model="name" >
</label>
<input type="button" value="添加" class="btn btn-primary" @click="add" >
<label>
搜索:
<input type="text" class="form-control" v-model="keywords">
</label>
</div>
</div>
<table class="table table-bordered table-hover table-striped" >
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Ctime</th>
<th>Opertation</th>
</tr>
</thead>
<tbody>
<!-- <tr v-for = "item in list" :key="item.id"> 仅能列表-->
<tr v-for = "item in search(keywords)" :key="item.id">
<td>{{ item.id }}</td>
<td v-text="item.name"> </td>
<td>{{ item.ctime | dateFormat('')}}</td> <!-- dateFormat('yyyy-mm-dd')-->
<td>
<a href="" @click.prevent="del(item.id)" >删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script>
Vue.http.options.root = 'https://192.168.1.4';
Vue.filter('dateFormat',function(dateStr,pattern=""){ //第二参数决定时间格式
var dt=new Date(dateStr)
var y = dt.getFullYear()
var m = dt.getMonth() + 1
var d = dt.getDate()
if(pattern && pattern.toLowerCase() === 'yyyy-mm-dd'){
return `${y}-${m}-${d}` //` ~的同位键 非' 构成魔法字符串
}else{
var hh = dt.getHours()
var mm = dt.getMinutes()
var ss = dt.getSeconds()
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
}) //全局过滤器 :所有实例都可以共享
new Vue({
el: '#app',
data: {
id:'',
name:'',
keywords:'',
list:[
{id:1,name:'奔驰',ctime:new Date()},
{id:2,name:'宝马',ctime:new Date()},
{id:3,name:'卡迪拉克',ctime:new Date()},
]
},
created(){ //页面加载调用数据
this.getAllList()
},
methods:{
add1(){
var car= {id: this.id,name:this.name,ctime: new Date()}
this.list.push(car)
this.id = ''
this.name= ''
},
add(){
this.$http.post('api/carsvuecrud/api.php?action=create',{name:this.name},{emulateJSON:true})
.then(result =>{ //参数3 {emulate 可以配置启用全局后省略 Vue.http.options.emulateJSON =true;
var result = result.body
if (result.status === 0){
this.getAllList()
//this.list =result.message
}else{
alert('获取数据失败')
}
})
},
getAllList(){ //获取服务器数据库中品牌的列表
this.$http.get('api/carsvuecrud/api.php?action=read')
.then(result =>{
var result = result.body
if (result.status === 0){
this.list =result.message
}else{
alert('获取数据失败')
}
})
},
del(id){
this.$http.get('api/carsvuecrud/api.php?action=delete&id=' + id) //启用全局根地址后可以简写
//this.$http.get('https://192.168.1.4/api/carsvuecrud/api.php?action=delete&id=' + id)
//不成功this.$http.post('https://192.168.1.4/api/carsvuecrud/api.php?action=delete' , {id:this.id},{emulateJSON:true})
.then(result =>{
var result = result.body
if (result.status === 0){
this.getAllList()
alert('删除成功')
}else{
alert('删除失败')
}
})
this.list.splice(index,1)
},
search(keywords){
/*var newList = []
this.list.forEach(item=>{
if(item.name.indexOf(keywords) != -1){
newList.push(item)
}
})
return newList
*/
returnthis.list.filter(item =>{
if(item.name.includes(keywords)){
return item
}
})
}
},
//私有过滤器 过滤器:名称 处理函数 通道符调用时先局部后全局
filters:{
dateFormat: function(dateStr,pattern=""){
var dt=new Date(dateStr)
var y = dt.getFullYear()
var m = (dt.getMonth() + 1).toString().padStart(2,'0')
var d = dt.getDate().toString().padStart(2,'0')
if(pattern && pattern.toLowerCase() === 'yyyy-mm-dd'){
return `${y}-${m}-${d}` //` ~的同位键 非' 构成魔法字符串
}else{
var hh = dt.getHours().toString().padStart(2,'0')
var mm = dt.getMinutes().toString().padStart(2,'0')
var ss = dt.getSeconds().toString().padStart(2,'0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
}
}
});
</script>
</body>
</html>
(九)、Vue动画
评论