MVVM思想
MVVM是前端视图层的概念,主要关注于 视图层分离
MVVM把前端的视图层,分为了 Model, View , VM ViewModel
基本结构
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!-- 相对应的Vue实例,会控制该元素的所有内容 -->
<div id="app">
<p>{{msg}}</p>
</div>
<script type="text/javascript">
//创建Vue实例
var vm=new Vue({
el:'#app', // 当前该实例要控制页面上的哪个区
data:{ //存放el中需要用到的数据
msg: "Hello Vue"
}
})
</script>
</body>
</html>
其中 #app 即Vue所控制的模块为V层
而Vue实例则为VM调度者
data可视为页面的M,用来保存数据
基本指令
v-cloak
因为浏览器渲染时,会暴露{{xxx}}(插值表达式闪烁问题),故我们使用v-cloak来隐藏。等待缓存后,再显示。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app">
<p v-cloak>{{msg}}</p>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
msg: "Hello Vue"
}
})
</script>
</body>
</html>
v-text
和插值表达式类似,但仍有区别:
v-text默认无闪烁问题
一旦解析到v-text,则会覆盖元素原本的内容,但插值表达式只会替换本身的占位符,而非元素内容
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<h1 v-text="msg">I am Tom</h1>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
msg: "Hello Vue"
}
})
</script>
</body>
</html>
v-html
v-html会识别data中,含有html标签的元素,便解析为html组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<h1 v-text="msg">I am Tom</h1>
<span v-html="html"></span>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
msg: "<h1>I am Tom</h1>",
html:"<h1>I am Tom</h1>"
}
})
</script>
</body>
</html>
v-bind的使用
用于 绑定属性的指令
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<input type="button" value="button" v-bind:title="Vuetitle" />
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
Vuetitle:"Hello"
}
})
</script>
</body>
</html>
v-bind 可简写为 :被绑定的属性
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<input type="button" value="button" :title="Vuetitle" />
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
Vuetitle:"Hello"
}
})
</script>
</body>
</html>
v-on 指令
v-on 用来绑定事件
其中绑定的事件需要在methods定义相关函数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<input type="button" value="button" v-on:click="show" />
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
text:"Hello"
},
methods:{ //在此处定义Vue实例所有的方法
show: function(){
alert('Hello')
}
}
})
</script>
</body>
</html>
v-on可简写为 @事件=“方法名”
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<input type="button" value="button" @click="show" />
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
text:"Hello"
},
methods:{ //在此处定义Vue实例所有的方法
show: function(){
alert('Hello')
}
}
})
</script>
</body>
</html>
跑马灯效果制作
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<h1>{{text}}</h1>
<input type="button" value="动起来 " @click="move">
<input type="button" value="静止" @click="stop">
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
text:"Hello",
intervalId :null //定时器id
},
// 分析:
// 1 需给按钮进行绑定事件
// 2 给事件进行相关业务代码:拿到字符串,调用字符串的substring截取操作。
// 3 实现点击按钮 则需要将2的代码放入定时器中
methods:{ //在此处定义Vue实例所有的方法
//ES6写法
move(){
//想要获取data的数据,需要this.xxx 来进行
var _this = this;
if(this.intervalId!=null){
return;
}
this.intervalId = setInterval(function(){
var start = _this.text.substring(0,1); //获取头字符串
var end = _this.text.substring(1); //获取末字符串
_this.text= end + start; //重新拼接
},100)
},
stop(){
clearInterval(this.intervalId);
//每当清除定时器后,重新赋值为null
this.intervalId=null;
},
show(){
alert(this.text)
}
}
})
</script>
</body>
</html>
事件修饰符
.stop 阻止冒泡
即 一个大组件和一个小组件都有点击事件,点击小的,则会都运行,通过阻止冒泡,来仅仅运行小组件.prevent 阻止默认事件
.capture 捕获机制
先输出外面的事件,再输出里面的事件。
.self
仅点击自己时,才触发事件
.once
仅发生一次
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- stop -->
<div style="width: 100px;height: 30px; background: red;" @click.capture="Out">
<!-- <input type="button" value="里边的组件" @click="inside"> -->
<input type="button" value="里边的组件" @click.stop="inside">
</div>
<!-- capture -->
<div style="width: 100px;height: 30px; background: red;" @click.capture="Out">
<!-- <input type="button" value="里边的组件" @click="inside"> -->
<input type="button" value="里边的组件" @click="inside">
</div>
<!-- self -->
<div style="width: 100px;height: 30px; background: red;" @click.self="Out">
<!-- <input type="button" value="里边的组件" @click="inside"> -->
<input type="button" value="里边的组件" @click="inside">
</div>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
},
methods:{
Out(){
alert("this is Out");
},
inside(){
alert("this is inside");
}
}
})
</script>
</body>
</html>
v-model
实现 数据双向绑定
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<input type="text" v-model:value="text">
<h1>{{text}}</h1>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
text:'Tom,Jerry,Lucy',
},
})
</script>
</body>
</html>
Vue使用样式
绑定类样式
1.数组
2.数字中使用三元表达式
3.数组中嵌套对象
4.直接适用对象
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<style>
.red{
color: red;
}
.blue{
color: blue;
}
.fw200{
font-weight: 200;
}
.active{
letter-spacing: 0.5em;
}
</style>
</head>
<body>
<div id="app">
<!-- 1.数组 -->
<!-- <h1 class="red">Hello</h1> ==> -->
<h1 :class="['red','active']">Hello</h1>
<!-- 2.数字中使用三元表达式 -->
<h2 :class="['red',flag?'active':'']">Wow</h2> <!-- ==> -->
<!-- 3.数组中嵌套对象 -->
<h3 :class="['red',{'active':flag}]">Hei</h3>
<!-- 4.直接适用对象 -->
<h4 :class="{ blue:true,active:false,fw200:true}">Hei</h4>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
flag:true
},
})
</script>
</body>
</html>
内嵌样式
1.采用对象的形式
其中对象就是无序键值对的集合
2.在data中定义,直接引用到:style中使用
3.引用多个data对象
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<p :style="{color: 'red', 'font-weight': 800}">Hello</p>
<p :style="style1">Wow</p>
<p :style="[color,font200]">Hei</p>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
style1: {color:'blue', 'font-weight':600},
color: {color:'green'},
font200: {'font-weight':200}
},
})
</script>
</body>
</html>
v-for
遍历普通数组
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- 遍历普通数组 -->
<p v-for="item in list">{{item}}</p>
<!-- 索引值 -->
<p v-for="(item,index) in list">{{index}} + {{item}}</p>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
list:['Tom','Jerry',"Lucy"]
},
})
</script>
</body>
</html>
遍历对象数组
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<p v-for="li in list">{{li.id}}+{{li.name}}</p>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
list:[
{id:1,name:"Tom"},
{id:2,name:"Jerry"},
{id:3,name:"Lucy"}
]
},
})
</script>
</body>
</html>
对象
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<p v-for="(val,key) in people">{{val}}+{{key}}</p>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
people:{
id:1,
name:"Tom"
}
},
})
</script>
</body>
</html>
注:
当Vue版本为2.2.x以上时,v-for需要附带key值进行唯一性标识
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<p v-for="li in list" :key="li.id">{{li.id}}+{{li.name}}</p>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
list:[
{id:1,name:"Tom"},
{id:2,name:"Jerry"},
{id:3,name:"Lucy"}
]
},
})
</script>
</body>
</html>
v-if & v-show
v-if:重新删除或创建元素 -->有较高的性能消耗
v-show:只是切换元素display:none样式
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<input type="button" value="Change" @click="flag=!flag">
<!-- 注意F12中Elements的变化 -->
<h1 v-if="flag">If</h1>
<h2 v-show="flag">Show</h2>
</div>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
flag:true
},
})
</script>
</body>
</html>
自定义键盘修饰符
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- 当@keyup时,每敲击一个按键,即产生一个事件 -->
<!-- .enter 是 敲击 Enter时才产生事件 -->
<input type="text" v-model="text" @keyup.enter="add()">
<p v-for="item in msg">{{item}}</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data:{
text:'',
msg:[
"Hello"
]
},
methods:{
add(){
this.msg.push(this.text)
},
},
})
</script>
</body>
</html>
相关按键修饰符
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right
.xxx(键盘码):自定义的键盘修饰符,通过键盘码,来认定那个按键的触发事件
自定义指令
vue所有的指令都需要 v-xxx 的格式
自定义全局
基本格式
//使用Vue.directive()来定义全局的指令
//参数1:指令的名称
//写时不写v- 用时则需要加上
//参数2:一个对象,有一些指令相关的函数。
Vue.directive('focus',{ })
参数2对象的一些规范说明:
Vue.directive('xxx',{
//钩子函数
bind:function(el){//每当指令判断到元素时,会立即执行bind函数,仅一次
},
inserted:function(){}, //元素插入到Dom中,会执行该函数,仅一次
updated:function(){}, //当VNode更新时,会执行该函数,可能多次
})
//其中,每个函数的第一个参数,为 el ,表示为被绑定指令的那个元素,其中el为Dom元素
//通常style元素的相关操作可放入bind,js最好放置于inserted
eg:
焦点事件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="text" v-focus>
</div>
<script type="text/javascript">
Vue.directive('focus',{
//由于一个元素,仅有被插入Dom后,才能被获取焦点,因此选择inserted
inserted:function(el){
el.focus();
},
})
var vm = new Vue({
el: "#app",
data:{
},
methods:{
},
})
</script>
</body>
</html>
自定义私有指令
var vm = new Vue({
directives:{ //私有指令
'xxx':{
bind:function(){
//...
}
}
})
eg:
字体改变
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<h1 v-color="'red'">{{text}}</h1>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data:{
text:"Hello"
},
directives:{ //私有指令
'color':{
bind:function(el,binding){ //参数2可通过一些参数获取值,其中字符串需额外添加''
el.style.color = binding.value;
}
}
}
})
</script>
</body>
</html>
简写形式
若代码仅写到 bind 和 update 则可简写
Vue.directive("xxx",function(el,binding){
//...
})
此简写法,会将内容都存入 bind和update中