Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的渐进式的前端框架。
Vue 只关注视图层, 采用自底向上增量开发的设计。
Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。
在Vue框架中,ViewModel是Vue.js的核心,它是一个Vue实例。Vue实例是作用于某一个HTML元素上的。那么ViewModel是如何实现双向绑定的呢?
Vue.js 是采用 Object.defineProperty 的 getter 和 setter,并结合观察者模式来实现数据绑定的。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 将它们转为 getter/setter,让 Vue 追踪依赖,在属性被访问和修改时通知变化。
工作原理及流程
1.当执行 new Vue() 时,Vue 就进入了初始化阶段,一方面Vue 会遍历 data 选项中的属性,并用 Object.defineProperty 将它们转为 getter/setter,实现数据变化监听功能
2.另一方面,Vue 的指令编译器Compile 对元素节点的指令进行扫描和解析,初始化视图,并订阅Watcher 来更新视图, 此时Wather 会将自己添加到消息订阅器中(Dep),初始化完毕
3.当数据发生变化时,Observer 中的 setter 方法被触发,setter 会立即调用Dep.notify(),Dep 开始遍历所有的订阅者,并调用订阅者的 update 方法,订阅者收到通知后对视图进行相应的更新。
图解:
Observer 数据监听器:能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者,内部采用Object.defineProperty的getter和setter来实现。
Compile 指令解析器:它的作用对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数。
Watcher 订阅者: 作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数。
Dep 消息订阅器:内部维护了一个数组,用来收集订阅者(Watcher),数据变动触发notify 函数,再调用订阅者的 update 方法。
1.独立版本
我们可以在 Vue.js 的官网上直接下载 vue.min.js 并用 <script> 标签引入。
2.NPM 安装
# 最新稳定版本$ npm install vue# 最新稳定 CSP 兼容版本$ npm install vue@csp# 开发版本(直接从 GitHub 安装)$ npm install vuejs/vue#dev
使用了 npm 安装项目,我们在 IDE(Eclipse、Atom等) 中打开该目录,结构如下所示:
目录解析
build:项目构建(webpack)相关代码config:配置目录,包括端口号等。我们初学可以使用默认的。node_modules:npm 加载的项目依赖模块src:这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件(assets: 放置一些图片,如logo等;components: 目录里面放了一个组件文件,可以不用;App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录;main.js: 项目的核心文件。)static:静态资源目录,如图片、字体等。test:初始测试目录,可删除.xxxx:文件这些是一些配置文件,包括语法配置,git配置等。index.html:首页入口文件,你可以添加一些 meta 信息或统计代码啥的。package.json:项目配置文件。README.md:项目的说明文档,markdown 格式
文本
数据绑定最常见的形式就是使用 {{...}}(双大括号)的文本插值:
<div id="app"> <p>{{ message }}</p></div>
Html
使用 v-html 指令用于输出 html 代码:
<div id="app"> <div v-html="message"></div></div> <script>new Vue({ el: '#app', data: { message: '<h1>JAVA</h1>' }})</script>
属性
HTML 属性中的值应使用 v-bind 指令。
以下实例判断 class1 的值,如果为 true 使用 class1 类的样式,否则不使用该类:
<div id="app"> <label for="r1">修改颜色</label><input type="checkbox" v-model="use" id="r1"> <br><br> <div v-bind:class="{'class1': use}"> v-bind:class 指令 </div></div> <script>new Vue({ el: '#app', data:{ use: false }});</script>
条件判断使用指令:v-if 、v-else、v-else-if
<div id="app"> <p v-if="seen">现在你看到我了</p> <template v-if="ok"> <h1>JAVA</h1> <p>学的不仅是技术,更是梦想!</p> <p>哈哈哈,打字辛苦啊!!!</p> </template></div> <script>new Vue({ el: '#app', data: { seen: true, ok: true }})</script>
循环使用 v-for 指令。v-for 指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名。
v-for 可以绑定数据到数组来渲染一个列表:
<div id="app"> <ol> <li v-for="site in sites"> {{ site.name }} </li> </ol></div> <script>new Vue({ el: '#app', data: { sites: [ { name: 'Baidu' }, { name: 'Google' }, { name: 'Taobao' } ] }})</script>
v-for 迭代对象
v-for 可以通过一个对象的属性来迭代数据:
<div id="app"> <ul> <li v-for="value in object"> {{ value }} </li> </ul></div> <script>new Vue({ el: '#app', data: { object: { name: 'test', url: 'test', slogan: '学的不仅是技术,更是梦想!' } }})</script>
v-for 迭代整数
v-for 也可以循环整数:
<div id="app"> <ul> <li v-for="n in 10"> {{ n }} </li> </ul></div>
Vue.js 监听属性 watch,我们可以通过 watch 来响应数据的变化。
以下实例通过使用 watch 实现计数器:
<div id = "app"> <p style = "font-size:25px;">计数器: {{ counter }}</p> <button @click = "counter++" style = "font-size:25px;">点我</button></div><script type = "text/javascript">var vm = new Vue({ el: '#app', data: { counter: 1 }});vm.$watch('counter', function(nval, oval) { alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!');});</script>
事件监听可以使用 v-on 指令:
通常情况下,我们需要使用一个方法来调用 JavaScript 方法。
v-on 可以接收一个定义的方法来调用。
<div id="app"> <!-- `greet` 是在下面定义的方法名 --> <button v-on:click="greet">Greet</button></div> <script>var app = new Vue({ el: '#app', data: { name: 'Vue.js' }, // 在 `methods` 对象中定义方法 methods: { greet: function (event) { // `this` 在方法里指当前 Vue 实例 alert('Hello ' + this.name + '!') // `event` 是原生 DOM 事件 if (event) { alert(event.target.tagName) } } }})// 也可以用 JavaScript 直接调用方法app.greet() // -> 'Hello Vue.js!'</script>
你可以用 v-model 指令在表单控件元素上创建双向数据绑定。v-model 会根据控件类型自动选取正确的方法来更新元素。
输入框
实例中演示了 input 和 textarea 元素中使用 v-model 实现双向数据绑定:
<div id="app"> <p>input 元素:</p> <input v-model="message" placeholder="编辑我……"> <p>消息是: {{ message }}</p> <p>textarea 元素:</p> <p style="white-space: pre">{{ message2 }}</p> <textarea v-model="message2" placeholder="多行文本输入……"></textarea></div> <script>new Vue({ el: '#app', data: { message: 'Runoob', message2: 'test' }})</script>
复选框
复选框如果是一个为逻辑值,如果是多个则绑定到同一个数组:
<div id="app"> <p>单个复选框:</p> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> <p>多个复选框:</p> <input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames"> <label for="runoob">Runoob</label> <input type="checkbox" id="google" value="Google" v-model="checkedNames"> <label for="google">Google</label> <input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames"> <label for="taobao">taobao</label> <br> <span>选择的值为: {{ checkedNames }}</span></div> <script>new Vue({ el: '#app', data: { checked : false, checkedNames: ['Google'] }})</script>
单选按钮
<div id="app"> <input type="radio" id="runoob" value="Runoob" v-model="picked"> <label for="runoob">Runoob</label> <br> <input type="radio" id="google" value="Google" v-model="picked"> <label for="google">Google</label> <br> <span>选中值为: {{ picked }}</span></div> <script>new Vue({ el: '#app', data: { picked : 'Runoob' }})</script>
select 列表
<div id="app"> <select v-model="selected" name="fruit"> <option value="">选择一个网站</option> <option value="www.baidu.com">Runoob</option> <option value="www.google.com">Google</option> </select> <div id="output"> 选择的网站是: {{selected}} </div></div> <script>new Vue({ el: '#app', data: { selected: 'www.baidu.com' }})</script>
Vue 要实现异步加载需要使用到 vue-resource 库。
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
Get 请求
以下是一个简单的 Get 请求实例:
window.onload = function(){ var vm = new Vue({ el:'#box', data:{ msg:'Hello World!', }, methods:{ get:function(){ //发送get请求 this.$http.get('URL').then(function(res){ document.write(res.body); },function(){ console.log('请求失败处理'); }); } } });}
如果需要传递数据,可以使用 this.$http.get('URL',{params : jsonData}) 格式,第二个参数 jsonData 就是传到后端的数据。
post 请求
post 发送数据到后端,需要第三个参数 {emulateJSON:true}。
emulateJSON 的作用: 如果Web服务器无法处理编码为 application/json 的请求,你可以启用 emulateJSON 选项。
window.onload = function(){ var vm = new Vue({ el:'#box', data:{ msg:'Hello World!', }, methods:{ post:function(){ //发送 post 请求 this.$http.post('URL',{name:"test",url:"test"},{emulateJSON:true}).then(function(res){ document.write(res.body); },function(res){ console.log(res.status); }); } } });}