#vue.js
MVVM把前端的视图层,把每个页面分成了三部分Model、View、VM
提供了数据双向绑定的思想(由VM提供)
Model:每个页面中单独的数据,获得的JSON数数据数组
View:就是每个页面中的html结构
VM:是一个调度者,分割了M和V,实现V和M之间的相互调用
前端的框架不提倡我们再手动去操作DOM元素,如:
$('#id').text('hello')
V:视图,即vue实例所控制的元素区域
<div id="app">
<p>{{ msg }}p>
div>
VM:创建出来的vm就是VM,数据之间的调度者
var vm = new Vue({
el: '#app', //表示当前new的这个vue实例,要控制页面上的哪个区域
data:{ //data存放el中要用到的数据
msg:'vue.js'
}
})
M:页面中保存的数据
VM中的data就是M,用来保存页面中的数据
解决差值表达式闪烁问题
{{ msg }}
当js文件的渲染未完成时,html结构中的p显示的是 {{msg}} 的字符串,当js渲染完成后才能显示 msg 的值,因此会有闪烁。
解决方法:
<style>
[v-cloak]{
display:none;
}
style>
<div id="app">
<p v-cloak>{{ msg }}p>
div>
这样就可以在未渲染完成时先隐藏p,等js加载完成后再显示出来。
显示出来和 {{ msg }} 的效果相同
覆盖元素中的所有内容,然后把内容当成html的标签渲染在页面上
<div v-html="msg2">div>
...
data:{
msg2:'<h1>我是一个H1h1>'
}
...
var vm = new Vue({
el: '#app',
data:{},
methods:{
show(){
alert('hello');
}
}
})
<div id="app">
<button type="button" v-on:click="roll">滚动button>
<button type="button" v-on:click="stop">停止button>
<p> {{ msg }} p>
div>
<script src="vue.js">script>
<script>
var timer1 = null;
var vm = new Vue ({
el:'#app',
data:{
msg:'这是一个跑马灯~'
},
methods:{
roll(){
if (timer1 != null)
{
clearInterval(timer1);
}
timer1 = setInterval ( () => {
var str1 = this.msg.substring(0,1);
var str2 = this.msg.substring(1);
this.msg = str2 + str1;
},200)
},
stop(){
clearInterval(timer1);
}
}
})
script>
① .stop 阻止冒泡
事件有冒泡的机制,如
<div @click="start">
<div @click="end">
div>
div>
当点击外部的div时,触发顺序为end->start,即从内至外进行冒泡。
使用.stop修饰符可以在被修饰的地方阻止冒泡事件
<div @click="start">
<div @click.stop="end">
div>
div>
此时点击外部的div,只会触发end,而不会再触发start(在end处被阻止)
② .prevent 阻止默认行为,实行新添加的行为
<a href="http://www.baidu.com" target="_blank" @click.prevent="waibu">点击去百度a>
点击上面的a标签,不会跳转到新的页面,而是调用methods中的wa
ibu方法
③.capture 捕获事件,从外向内执行
冒泡事件是从里向外执行,而捕获事件则是从外向内执行。
<div @click.capture="waibu">
<button type="button" @click="neibu">buttonbutton>
div>
此时点击Div,会先触发waibu,再触发neibu
④.self只有事件是在元素自身的时候,才会触发
v-bind只能实现数据的单向绑定,从 M 绑定到 V
使用 v-model 可以实现数据的双向绑定
<div> {{ msg }} div>
<input type="text" v-model="msg">
v-model 只能用在表单元素中!
<input type="text" v-model='n1'>
<select name="" id="" v-model="opt">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" v-model='n2'>
<input type="button" value="=" @click="cal">
<input type="text" v-model='result'>
cal(){
var codeStr = 'parseInt(this.n1)' + this.opt + 'parseInt(this.n2)';
this.result = eval(codeStr);
1.使用字符串拼接,拼接出计算代码语句
2.使用eval解析代码语句并执行
}
<h1 v-bind:class="['class1','class2','class3']">
这是一个h1
h1>
<h1 v-bind:class="['thin','red',flag?'active':'']">
这是一个很大的h1
h1>
<h1 v-bind:class="['thin','red',{'active':flag}]">
这是一个很大的h1
h1>
html:
<h1 v-bind:class="classCss">
这是一个很大的h1
h1>
js:
classCss:{red:true,thin:true,italic:true}
//直接把要的类写成一个 **对象**,再把对象直接绑定在元素的class中
<h1 v-bind:style="{color:'red','font-weight':200}">
这是一个很大的h1
h1>
<p v-for="(item,i) in list"> 索引值:{{ i }} 数据值:{{ item }} p>
js:
data:{
list:[0,1,2,3,4,5,6]
}
<p v-for="(item,i) in list"> 索引值:{{ i }} id:{{ item.id}} 姓名:{{ item.name }} </p>
js:
data:{
list:[
{id:1,name:'n1'},
{id:2,name:'n2'},
{id:3,name:'n3'},
{id:4,name:'n4'}
]
}
<p v-for="(val,key,i) in user"> 值是:{{ val }} 键是:{{ key }} 索引:{{ i }} </p>
js:
data:{
user:{
id:1,
name:'tony',
gender:'male'
}
}
<p v-for="count in 10">这是第 {{ count }} 次循环p>
<div id="app">
<label>输入编号</label><input type="text" v-model="id">
<label>输入姓名</label><input type="text" v-model="name">
<input type="button" @click="add" value="添加">
<p v-for="item in list" v-bind:key="item.id">
<input type="checkbox"/>
id:{{ item.id }} name:{{ item.name }}
</p>
</div>
<script src="vue.js"></script>
<script>
var vm = new Vue ({
el:"#app",
data:{
id:'',
name:'',
list:[
{id:1,name:'a'},
{id:2,name:'b'},
{id:3,name:'c'},
{id:4,name:'d'},
]
},
methods:{
add(){
this.list.unshift({id:this.id,name:this.name})
}
}
})
</script>
当使用 v-for 循环的时候,如果要对循环出来的数据做唯一处理,则可以为每个数据绑定唯一的 key (可以是number或者string)
<button type="button" @click="flag=!flag">切换button>
<h1 v-if="flag">v-ifh1>
<h1 v-show="flag">v-showh1>
v-if:每次都会创建或删除元素,有较高的切换性能损耗
v-show:不对DOM进行删除创建操作,每次只是改变了 display 的样式
如果涉及到元素频繁的切换,则最好不要用 v-if
如果元素可能永远也不会被显示,则推荐使用v-if
Vue.filter(‘filter-name’,function(data){
…
})
${变量1}-${变量2}
使用 tab 键上的反引号,内部的每个变量用 ${} 包括,就可以实现字符串的拼接了
v-on:keyup.enter = “” 代表党抬起回车键时触发
v-on:keyup.13 = “” 代表抬起 keyCode 为 13的按键时触发
但是不是每个按键都有名字定义,大部分按键只有按键码,因此把按键名和按键码相绑定
Vue.config.keyCodes.f2 = 112
// 使用 Vue.directive() 定义全局的指令 v-focus
Vue.directive('focus', {
bind: function (el) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次
// 注意: 在每个 函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象
// 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用
// 因为,一个元素,只有插入DOM之后,才能获取焦点
// el.focus()
},
inserted: function (el) { // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】
el.focus()
// 和JS行为有关的操作,最好在 inserted 中去执行,放置 JS行为不生效
},
updated: function (el) { // 当VNode更新的时候,会执行 updated, 可能会触发多次
}
})
// 自定义一个 设置字体颜色的 指令
Vue.directive('color', {
// 样式,只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联的样式
// 将来元素肯定会显示到页面中,这时候,浏览器的渲染引擎必然会解析样式,应用给这个元素
bind: function (el, binding) {
// el.style.color = 'red'
// console.log(binding.name)
// 和样式相关的操作,一般都可以在 bind 执行
// console.log(binding.value)
// console.log(binding.expression)
el.style.color = binding.value
}
})
js:
Vue.component('mycom',{
template:'#tmpl'
})
html:
<template id="tmpl">
<div>
<h3></h3>
<h3></h3>
<h3></h3>
</div>
</template>
//注意,使用这种方法定义的template标签,要写在Vue实例范围的外面,否则template标签也会出现
var vm = new Vue({
el:"#app",
data:{},
methods:{},
components:{
login:{ // 定义login组件,只能在app中使用
template:'呵呵哒
'
}
}
})
① 组件可以有自己的data数据
② 实例中的data可以是一个对象,但是组件中的data必须是一个方法
components:{
com1:{
template:'{{ msg }}{{ info }}
'
data(){
return {
msg:'hello',
info:'joey'
}
}
}
}
③ 这个方法的内部还必须返回一个对象
④ 组件中的 data 使用方式和实例中的data使用方式一样
子组件和父组件的定义:
如果一个组件出现在另一个组件的内部,则这个组件是外层组件的子组件
<div id="app3">
<applecomponent v-bind:b="vparam">applecomponent>
<mycomponent v-bind:b="vparam">mycomponent>
<templecomponent v-bind:b="vparam">templecomponent>
div>
如图,app3是一个实例,可以看成一个大的组件,其中的mycomponent是一个全局定义的组件,此时,全局定义的组件可以从其所在实例中继承数据。
<div id="app">
<p>{{ msg }}p>
<com1 v-bind:parentdata="msg">com1>
// 1.通过属性绑定,把父组件的数据赋值给com1组件
div>
<script>
var vm = new Vue({
el: '#app',
data:{
msg:'hello'
},
components:{
com1:{
template:'{{ parentdata }}
',
props:['parentdata']
//2.子组件要获取父组件
}
}
})
script>
在父组件的methods中定义的方法,可以通过方法绑定,将其加载到子组件中
html:
<com1 v-on:func="show"></com1>
js:
var vm = new Vue({
el:"#",
methods:{
show(){
//show函数
}
}
})
<div id="app">
<p ref="myP">今天的天气不错</p>
<button type="button" @click="say">say</button>
</div>
<script>
var vm = new Vue({
el: '#app',
methods:{
say(){
alert(this.$refs.myP.innerText)
}
}
})
ref不仅可以获得DOM,还可以获得组件(的数据和函数等)
<div id="app">
<input type="text" v-model="msg">
</div>
<script>
var vm = new Vue({
el: '#app',
data:{
msg:'vue.js'
},
watch:{
msg:function(){ //当msg发生改变时,会自动触发该函数
console.log('监听msg');
}
}
})
</script>
``