Vue.js:探索前端框架的奥秘

发表时间: 2019-03-20 14:28

一、什么是Vue.js

Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的渐进式前端框架。

Vue 只关注视图层, 采用自底向上增量开发的设计。

Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件

二、实现MVVM模式

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。

三、Vue.js工作原理(见下图)

在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 方法。

四、Vue.js 安装

1.独立版本

我们可以在 Vue.js 的官网上直接下载 vue.min.js 并用 <script> 标签引入。

2.NPM 安装

# 最新稳定版本$ npm install vue# 最新稳定 CSP 兼容版本$ npm install vue@csp# 开发版本(直接从 GitHub 安装)$ npm install vuejs/vue#dev

五、Vue.js 目录结构

使用了 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 格式

六、Vue.js 模板语法

文本

数据绑定最常见的形式就是使用 {{...}}(双大括号)的文本插值:

<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>

七、Vue.js 条件语句

条件判断使用指令: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>

八、Vue.js 循环语句

循环使用 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 监听属性

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>

十、Vue.js 事件处理

事件监听可以使用 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>

十一、Vue.js 表单

你可以用 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.js Ajax(vue-resource)

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); }); } } });}