vue学习简单入门
1、MVVM思想
- M:即Model,模型。包括数据和一些基本操作。
- V:即View,视图。页面渲染结果。
- VM:即View-Model,模型与视图间的双向操作。(无需开发人员干涉)
在MVVM之前,开发人员从后端获取到需要的数据模型,然后通过DOM操作Model渲染到View中。而后当用户操作视图,我们还需要通过DOM获取到View中的数据,然后同步到Model中去。
而MVVM中的VM就是要做这样的事情:把DOM操作完全封装起来,开发人员不用再关心Model和View之间是如何影响的。
2、Vue简介
3、入门案例
4、概念
1)、创建Vue实例
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>{{a}}</h1>
<button v-on:click="b">点击</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var vue = new Vue({
el: '#app',
data: {
a: 666
},
methods: {
b() {
this.a--;
}
}
})
</script>
</body>
</html>
1、new 出来的vue实例管控这 id选择器为app的标签,整个div。
2、想要给这个div绑定一些数据,我们就要将所有的数据写在vue对象的另一个属性data里面。由于未来可能有很多的数据,所以我们写成一个对象{},这样很多的key-value都能用。
3、在标签体里面我们可以使用vue的插值表达式: {{}} 就可以从数据data里面取出key的value。
4、现在数据变,视图就会变目前是一个单向的过程。
5、这么强大的功能,我们只需要让vue管控这个元素,而元素里面的所有东西,我们都可以使用vue更强大的功能,更简化的语法。
创建vue实例(new),关联页面的模板,将自己的数据(data)渲染到关联的模板上。这个渲染过程是自动的。而且,只要data里的数据发生变化,那么模板也会跟着变。我们把这个过程称为响应式。
我们还可以通过指令,来简化对DOM的操作。比如:我们要双向绑定,我们使用v-model
,点击事件的时候可以使用v-on
,也可以绑定自定义的方法等。
声明的方法要放在vue的methods属性对象里面。
在方法中使用data中的数据,要用this.xx的方式。
总结:
el
:绑定元素;data
:封装数据;methods
:封装方法;- ... vue对象还有很多属性,上面3个最常用。
2)、插值表达式
①、说明
格式:{{表达式}}
- 该表达式支持js语法,可以调用js内置函数(但是必须要有返回值)。
- 表达式必须有返回结果。
- 可以直接获取vue实例中定义的数据和函数。
如:{{msg}}、{{1+1}}、{{func()}}、{{1+1=2?正确:错误}}
②、插值闪烁
使用{{}}这种方式在网速较慢的时候会出现问题。在数据未加载完成时,页面会显示原始的{{}},加载完毕后才显示正确数据,我们称它为插值闪烁。
F12开发者模式下,模拟网速慢,Network 可以调成slow 3G,就可以看到效果。
缺点:{{}}插值表达式只能用在标签体里面,如果标签的属性也要调用vue中定义的数据或函数,就不能使用{{}}插值表达式了。
那么,我们如何给属性动态的绑定vue实例定义的值呢?
3)、Vue指令
①、单向绑定: v-bind
{{}}只能给标签体绑定值,而给标签的属性绑定值则使用v-bind指令。
使用:
- v-bind:属性名="数据"
- :属性名="数据"
对标签的class和style属性的增强:
我们只需要写一个对象,然后这个对象的某个属性值跟vue实例中的数据进行绑定。
如: :class='{active:isActive,textDanger:hasError}'
如: :style='{color:color1,fontSize:size}'
②、双向绑定: v-model
v-model一般用于表单项、自定义组件。只有它们才需要双向绑定。
我们只需要将元素的跟模型里面的某一个属性进行绑定,以后我们页面输入框值变了,我们data中属性的值就会跟着变。而且,属性的值变化了,输入框里的值对应也会跟着变。这就是双向绑定的过程。
在我们日常开发中,我们都是使用v-model将我们表单里面的某一项跟数据进行绑定,这样我们实时来获取值也会很方便。
③、事件处理: v-on
我们用v-on绑定事件,我们可以直接对data里面的数据进行操作,而我们用jquery等框架则是不可以的。
使用:
- v-on:事件名="方法名"
- @事件名="方法名"
事件修饰符:
阻止事件的默认行为,如事件冒泡等,可以使用事件修饰符。
事件修饰符,是由点开头的指令后缀来表示的。
- .stop:阻止事件冒泡到父元素。
- .prevent:阻止默认事件发生。
- .capture:使用事件捕获模式
- .self:只有元素自身触发事件才执行。(冒泡或捕获的都不执行)
- .once:只执行一次。
按键修饰符:
在监听键盘事件时,我们经常需要检查常见的键值。Vue允许为v-on在监听事件时添加按键修饰符。
// 只有在keyCode为13的时候调用vm.submit()
<input v-on:keyup.13="submit"/>
记住所有的keyCode比较困难,所以Vue为所有常见的键值取了别名。
//同上
<input v-on:keyup.enter="submit"/>
//缩写语法
<input @keyup.enter="submit"/>
全部的按键别名
- .ctrl
- .enter
- .tab
- .delete
- .esc
- .space
- .up
- .down
- .left
- .right
④、单向绑定:v-text 和 v-html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<span v-html="msg"></span>
<span v-text="msg"></span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var vue = new Vue({
el: '#app',
data: {
msg: '<h1>hello</h1>'
}
})
</script>
</body>
</html>
- v-html:不会对html标签进行转义,直接会在浏览器中显示标签。
- v-text:会对html标签进行转义。
- 这2个指令都是单向绑定的。
⑤、遍历循环:v-for
- 1、显示user信息: v-for="item in items"
- 2、获取数组下标: v-for="(item,index) in items"
- 3、遍历对象:
v-for="value in obj"
v-for="(value,key) in obj"
v-for="(value,key,index)in obj" - 4、遍历的时候都加上 :key来区分不同的数据,可以提高vue渲染的效率。
⑥、判断与显示:v-if 和 v-show
- v-if:顾名思义,条件判断。当得到的结果为ture时,所在的元素才会被渲染。
- v-show:得到的结果为true时,所在的元素才会被显示。(相当于设置了display:none)
1、经常与v-if一起使用的还有:v-else、v-else-if。
2、v-if与v-for搭配使用时,v-if的优先级是低于v-for的。也就是v-for先遍历,拿到遍历的对象再根据v-if判断。
4)、计算属性
某些结果是基于之前的数据实时计算出来的,这种情况我们可以利用计算属性来完成。
计算属性computed
是vue实例中的一个属性,所有需要动态计算的属性,都可以在写在这里。
它的特点是:该属性依赖的任意一个值发生变化,都会触发它的重新计算。
5)、侦听器
侦听器(watch),也是vue实例的一个属性。watch可以让我监控一个值的变化,从而做出相应的反应。
6)、过滤器
过滤器(filters)也是vue实例的一个属性,它是一个方法,它可以把要过滤的值当做参数传入进来,进行逻辑处理。
过滤器常用来处理文本格式的操作。过滤器可以用在2个地方:
- ① 双花括号插值
- ② v-bind表达式
过滤器如果写在vue实例里面,则是一个局部过滤器,它只可以在当前的vue实例中可以使用。如果要创建全局的过滤器写法是: Vue.filter(..);
7)、组件化
在项目开发过程中,往往在不同的页面中,会使用相同的部分,为了让这些重复的部分方便复用,我们就可以把它作为组件。
在vue里,所有的vue实例都是组件。我肯可以通过组件之间的灵活组合,完成更强大的功能。
例如:你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其他的像导航链接、博文之类的组件。
①、全局声明一个组件:
Vue.component('my-component-name', {
// ... 选项 ...
})
这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。比如:
Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })
new Vue({ el: '#app' })
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
在所有子组件中也是如此,也就是说这三个组件在各自内部也都可以相互使用。
②、局部声明一个组件:
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
在这些情况下,你可以通过一个普通的 JavaScript 对象来定义组件:
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
然后在 components 选项中定义你想要使用的组件:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
对于 components 对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
注意局部注册的组件在其子组件中不可用。例如,如果你希望 ComponentA 在 ComponentB 中可用,则你需要这样写:
var ComponentA = { /* ... */ }
var ComponentB = {
components: {
'component-a': ComponentA
},
// ...
或者如果你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
注意在 ES2015+ 中,在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写,即这个变量名同时是:
用在模板中的自定义元素的名称
包含了这个组件选项的变量名
说明: 组件的data() 是一个方法的返回。为什么呢?因为这样,我们每声明一个组件、每使用一个组件,它的数据都是调用这个方法而返回的一个新对象。那么每一个组件的数据,统计都是独立统计的。而如果返回以前的data的话,那么任何一个组件返回的对象都是同一个实例,那么就导致一处修改其他地方也会跟着修改,这样就达不到组件复用的效果了。
总结:
- 组件其实也是一个vue实例,因此它在定义时也会接收:data、methods、生命周期函数等。
- 不同的是,组件不会与页面元素进行绑定,否则就无法复用了。因此没有#el元素。
- 但是组件渲染需要html模板,所以增加了template属性,值就是html模板。
- 全局组件定义完毕,任何vue实例都可以直接在html中通过组件名来使用该组件。
- data必须是一个函数,不再是一个对象。
8)、生命周期钩子函数
每个vue实例在被创建时都呀经历一系列的初始化过程:创建实例、装载模板、渲染模板等等。
为了简化开发,vue在生命周期中的每个状态都设置了钩子函数(也是监听函数)。每当vue实例处于不同的生命周期时,对应的生命周期函数就会被触发。
测试各个生命周期函数的执行时机:
created 钩子可以用来在一个实例被创建之后执行代码:
new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
// => "a is: 1"
在实例生命周期的不同阶段被调用,如 mounted、updated 和 destroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。
不要在选项属性或回调上使用箭头函数,
比如 created: () => console.log(this.a) 或vm.$watch('a', newValue => this.myMethod())。
因为箭头函数并没有 this,this 会作为变量一直向上级词法作用域查找,直至找到为止,
经常导致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。
9)、vue的Live Template
<template>
<div></div>
</template>
<script>
//这里可以导入其他文件,如:组件、工具js、第三方插件js、json文件、图片文件等
//例如:import [组件名称] from [组件路径];
export default {
//import引入的组件需要注入到对象中才可以使用
components: {},
//父子组件传递数据
props: {},
data(){
//这里存放数据
return {};
},
//计算属性,类似于data概念
computed: {},
//侦听器,监听data中的数据变化
watch: {},
//方法集合
methods: {
},
//生命周期 - 创建完成(可访问当前this实例)
created() {},
//生命周期 - 挂载完成(可访问DOM元素)
mounted(){
},
//生命周期 - 创建之前
beforeCreated(){},
//生命周期 - 挂载之前
beforeMount(){},
//生命周期 - 创建之前
beforeCreated(){},
//生命周期 - 更新之前
beforeUpdate(){},
//生命周期 - 更新之后
updated(){},
//生命周期 - 销毁之前
beforeDestroy(){},
//生命周期 - 销毁完成
destroyed(){},
//如果页面有keep-alive缓存功能,这个函数a会触发
activated(){},
}
</script>
<style lang="scss" scoped>
/*@import url(); 引入公共的css类*/
</style>