MVVM
MVVM是Model-View-ViewModel的简写.MVVM就是将其中的View的状态和行为抽象化,让我们将视图UI(或者说前端界面)和业务逻辑分开.当然这些事ViewModel已经帮我们做了,它可以取出Model的数据同时帮忙处理View中由于需要展示内容而涉及的业务逻辑.
VUE
什么是Vue.js
Vue是一套用于构建用户界面的渐进式框架.与其他框架不同的是,Vue被设计为可以自底向上逐层应用.Vue的核心只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合.
Vue.js是前端的主流框架之一,和Angular.js,React.js一起,并成为前端三大主流框架.
Vue.js优点
1.体积小.
2.运行效率更高
用JQuery或者原生的JavaScript DOM操作函数对DOM频繁操作的时候,浏览器要不停的渲染新的DOM树,导致页面看起来非常卡顿.
基于虚拟dom,一种可以预先通过JavaScript进行各种计算,把最终的DOM操作计算出来并优化的技术,由于这个DOM操作属于预处理操作,并没有真实地操作DOM,所以叫做虚拟DOM.最后在计算完毕才真正将DOM操作提交,将DOM操作变化反映到DOM树上.
3.双向数据绑定,简化DOM操作
通过MVVM思想实现数据的双向绑定,让开发者不用再操作DOM对象.
4.生态丰富,学习成本低
市场上拥有大量成熟,稳定的基于vue.js的框架以及常用组件,对初学者友好,入门容易,学习资料多.
vue的安装
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
第一个vue程序
1.导入开发版本的vue.js
2.创建vue实例对象,设置el属性和data属性
3.使用简洁的模板语法把数据渲染到页面上
vue.js的核心是一个允许采用简洁的模板语法来声明式的将数据渲染进DOM的系统.
<div id="app">
<!-- {{{ 变量,来自于vue中的data里面定义的变量 }}} -->
{{ message }} <!-- 插值表达式,不允许写其他的语句例如流程控制语句,声明变量, 表达式最终需要返回一个结果显示-->
<p>
{{ message }}
</p>
</div>
<script type="text/javascript">
// 创建一个vue对象,使得此对象与 id="app"的div进行绑定
var app = new Vue({
el: '#app',//将指定的标签与vue对象绑定在一起了
data: {//就是定义数据 vue对象实现数据和标签之间双向数据绑定
message: 'Hello Vue1111!'
}
})
</script>
此程序运行的结果就是在页面显示两行Hello Vue1111!
代码解析:
{{ 变量 }}模板语法,插值表达式获取数据
new Vue();创建vue对象(VM对象)
el:数据挂载的DOM对象
vue会管理el选项命中的元素及其内部的后代元素
可以使用其他的选择器,但是建议使用ID选择器
可以使用其他的闭合标签,不能使用HTML和body
data:{ message: ‘Hello Vue1111!’}
model数据.vue中用到的数据定义在data中
data中可以写复杂类型的数据,比如对象和数组
渲染复杂类型数据时,遵守js的语法即可
模板语法
迄今为止,在我们的模板中,我们一直都只绑定简单的键值,但实际上,对于所有的数据绑定.vue.js都提供了完全的JavaScript表达式支持.
例如
{{ number + 1}}
{{ ok ? ‘yes’ : ‘no’ }}
{{ message.split(‘’).reverse().join(‘’) }}
这些表达式会在所属vue实例的数据作用域下作为JavaScript被解析.有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效
{{ var a = 1 }}//因为这是一个语句,并不是表达式
{{ if (ok) { return message } }}//控制流也不会生效,如果需要可以使用三元表达式
vue指令
指令带有前缀v-开头,以表示他们是vue提供的特殊属性.
v-text
作用是设置标签的文本内容
默认写法会替换全部内容,使用插值表达式可以替换指定内容
v-html
作用是设置元素的innerHTML
内容中有html结构会被解析为标签
内部支持写表达式
这样我们就可以把v-text与v-html拿来做一个对比
<div id="app">
<p>{{ msg1 }}-bbbbb</p><!-- 插值表达式,不会覆盖标签中的其他内容 -->
<p v-text="msg1"></p> <!--v-text覆盖标签中的其他 把内容当文本处理,不能解析内容中的标签-->
<p v-html="msg1"></p> <!--v-html覆盖标签中的其他, 可以将内容中的标签解析 -->
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
msg1:"<b>aaaaaa</b>",
}
})
</script>
上面代码运行的结果是
<b>aaaaaa</b>-bbbbb
<b>aaaaaa</b>
aaaaaa
v-on
作用是为元素绑定事件
事件名不需要写on指令可以简写为@
绑定的方法定义在methods属性中,可以传入自定义参数
v-model
作用是便捷的设置和获取表单元素的值
绑定的数据会和表单元素相关联
绑定的数据与表单中元素的值,实现双向数据绑定
<div id="app">
<!-- v-model='数据' 将文本框的value属性值,绑定到data中的account -->
<input type="text" v-model="account" value="" />
<!-- 点击测试按钮时,文本框中的内容会变成"222222" -->
<input type="button" value="测试" v-on:click="test()" />
<!-- 更改文本框中的内容 p标签的内容也会接着改变 -->
<p>{{account}}</p>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
// 默认的是111
account:"111"
},
methods:{
/* 在vue中自定义的函数都写在methods中*/
test(){
//this代表的就是vue对象
this.account = "222222";
}
}
})
</script>
v-show
作用是根据真假切换元素的显示状态
原理是修改元素的display,实现显示隐藏
指令后面的内容,最终都会解析为布尔值
值为true元素显示,值为false元素隐藏
数据改变之后,对应元素的状态会同步更新
v-if
作用是根据表达式的真假切换元素的显示状态
本质是通过操纵DOM元素来切换
显示状态表达式的值为true,元素存在于DOM中,如果为false,从DOM中删除
频繁的切换使用v-show,反之使用v-if,在需要大量执行切换显示状态的操作的时候,前者的切换消耗更小
<div id="app">
<!--
v-show="布尔值" false--为标签添加display:none属性,隐藏标签,dom还是存在,操作数量多,效率高
v-if="布尔值" false -- 将标签从网页中删除了,操作数量多,效率低
-->
<p v-show="isShow">aaaaaa</p>
<p v-show="num>5">cccccc</p>
<p v-if="isShow">aaaaaa</p>
<p v-else>bbbbbb</p> <!-- v-else if不成立显示,必须两个标签是相邻的-->
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
isShow:false,
num:10
}
})
</script>
程序运行的结果是
cccccc
bbbbbb
v-bind
作用是为元素绑定属性
完整写法是v-bind:属性名
简写的话可以直接省略v-bind,只保留:属性名
<div id="app">
<!-- v-bind 为标签中的属性动态的赋值
v-bind:src="data"
:src="data"
-->
<img v-bind:src="imgArray[index]" />
<img :src="imgArray[index]" />
<input type="button" value="下一张" @click="next()" />
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
imgArray:["img/1.jpg","img/2.jpg"],
index:0
},
methods:{
next(){
this.index++;
}
}
})
</script>
上面的代码就可以实现图片的切换
v-for
作用是根据数据生成列表结构
数组经常和v-for结合
使用语法是(item,index)in 数据
item和index可以结合其他指令一起使用
数组长度的更新会同步到页面上是响应式的
vue实例生命周期
每个vue实例在被创建时都要经过一系列的初始化过程----例如,需要设置数据监听,编译模板,将实例挂载到DOM并在数据变化时更新DOM等.同时在这个过程也会执行一些叫做生命周期钩子的函数,这给用户在不同阶段添加自己代码的机会.
beforeCreate(创建前)
在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el和data并未初始化,因此无法访问methods,data等上的方法和数据.
created(创建后)
实例已经创建完成之后被调用,在这一步,实例已完成以下配置:数据观测、属性和方法的运算,watch/event事件回调,完成了data 数据的初始化,el没有。 然而,挂在阶段还没有开始, $el属性目前不可见,这是一个常用的生命周期,因为你可以调用methods中的方法,改变data中的数据,并且修改可以通过vue的响应式绑定体现在页面上,,获取computed中的计算属性等等,通常我们可以在这里对实例进行预处理,也有一些童鞋喜欢在这里发ajax请求,值得注意的是,这个周期中是没有什么方法来对实例化过程进行拦截的,因此假如有某些数据必须获取才允许进入页面的话,并不适合在这个方法发请求,建议在组件路由钩子beforeRouteEnter中完成
beforeMount
挂在开始之前被调用,相关的render函数首次被调用(虚拟DOM),实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,注意此时还没有挂在html到页面上。
mounted
挂在完成,也就是模板中的HTML渲染到HTML页面中,此时一般可以做一些ajax操作,mounted只会执行一次。
beforeUpdate
在数据更新之前被调用,发生在虚拟DOM重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程
updated(更新后)
在由于数据更改导致地虚拟DOM重新渲染和打补丁只会调用,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,然后在大多是情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用
beforeDestroy(销毁前)
在实例销毁之前调用,实例仍然完全可用,
- 这一步还可以用this来获取实例,
- 一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的dom事件
destroyed(销毁后)
在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用
在这个时间段,我们就可以添加对应的代码:
beforeCreate: function () {
console.log('beforeCreatea');
}
vue-cli项目的搭建
vue-cli官方提供的一个脚手架,用于快速生成一个vue的项目模板.预先定义好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一个骨架项目,这个骨架项目就是脚手架,我们开发会变得更加的快速.
主要的功能:
1.统一的目录结构
2.本地调试
3.热部署
4.单元测试
5.集成打包上线
需要的环境:
node.js
简单的说node.js就是运行在服务端的JavaScript.
node.js是一个基于Chrome JavaScript运行时建立的一个平台,它是一个事件驱动i/o服务端JavaScript环境,基于Google的v8引擎,v8引擎执行JavaScript的速度非常快,性能非常好.
安装完成之后可以通过node -v,npm -v命令验证是否安装成功
npm
npm是node.js的包管理工具,用来安装node.js的扩展.npm是JavaScript的包管理工具,也是世界上最大的软件注册表.
使用HbuilderX快速搭建
使用HbuilderX搭建vue脚手架的前提就是必须安装好node.js.
我们在HbuilderX新建一个项目,但是与之前不同的是这个时候我们的模板不再是基本HTML项目,而是vue项目.新建项目的时候时间可能会有些长,耐心等待就好.项目创建好了之后我们可以直接选中这个项目,Alt+c打开终端.在终端输入npm run serve就可以运行起来.
我们当然也可以自己写各种组件(或者说页面),在src目录下直接新建一个vue文件(不是html文件,整个项目只有一个html文件).
在写自己的组件之前,需要改变src目录下的app.vue文件为
<template>
<div id="app">
<!-- router-view用来显示不同组件 -->
<router-view>
</router-view>
</div>
</template>
<script>
export default{
}
</script>
<style>
</style>
其次main.js也要改变
import Vue from 'vue'
// 导入默认组件
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
render: h => h(App)
})
在src目录下新建一个router目录,新建一个index.js,这个js文件就是我们的路由配置信息.
// router配置文件
import Vue from 'vue';
import router from 'vue-router'; /* 导入路由*/
// 导入组件
import Login from "../Login.vue";
Vue.use(router);
//定义组件路由
var rout = new router({
routes: [{
path: '/login', //为组件定义地址
name: 'Login',
component: Login // 与导入的对应起来
}]
});
//导出路由对象
export default rout;
创建好index.js文件后,还需要在命令行输入npm i vue-router@3.5.3引入路由.
当准备工作做好之后,我们就可以写自己的组件了.