一.vue实例

每个vue应用都是通过Vue构造函数创建的一个新的实例开始的:

var vm = new Vue({
//选项对象
})

在这其中vm(viewModel的简称)通常都表示vue实例的变量名。当创建一个vue实例,你都可以传入一个选项对象作为参数,完整的选项对象,你可能需要查看API文档

一个vue应用应该由一个通过new Vue构造的根实例和许多可嵌套可复用的组件构成,这也就是说所有的组件都是vue实例。

二.数据与方法

当一个vue实例被创建完成之后,就会向它的vue响应系统中加入了data对象中能找到的所有属性,当这些属性的值发生改变之后,视图就会发生响应,也就是更新相应的值。我们来看一个例子:

//源数据对象
var obj = { name:"eveningwater" };
//构建实例
var vm = new Vue({
data:obj
}) //这两者是等价的
vm.name === obj.name;
//这也就意味着
//修改data对象里的属性也会影响到源数据对象的属性
vm.name = "waterXi";
obj.name;//"waterXi"
//同样的,修改源数据对象的属性也会影响到data对象里的属性
obj.name = 'stranger';
vm.name;//"stranger"

可能需要注意的就是,只有data对象中存在的属性才是响应式的,换句话说,你为源数据对象添加一个属性,根本不会影响到data对象。如:

obj.sex = "男";
vm.sex;//undefined
obj.sex;//'男'
obj.sex = "哈哈哈";
vm.sex;//undefined

这也就意味着你对sex的修改并不会让视图更新,如此一来,你可能需要在data对象中初始化一些值,如下:

data:{
str:'',
bool:false,
arr:[],
obj:{},
err:null,
num:0
}

查看此处具体示例

只是还有一个例外Object.freeze(),这个方法就相当于锁定(冻结)一个对象,使得我们无法修改现有属性的特性和值,并且也无法添加新属性。因此这会让vue响应系统无法追踪变化:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>freeze</title>
</head>
<body>
<div id="app">
<span>{{ message }}</span>
<button type="button" v-on:click="reverseMessage">反转信息</button>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码如下:

      var obj = {
message: "hello,vue.js!"
}
//阻止对象
Object.freeze(obj);
var app = new Vue({
el: "#app",
data:obj,
methods: {
reverseMessage: function() {
this.message = this.message.split("").reverse().join("");
}
}
});

如此一来,无论我们怎么点击按钮,都不会将信息反转,甚至页面还会报错,如下图:


可前往此处具体示例自行查看效果。

当然除了数据属性以外,vue还暴露了一些有用的实例属性和方法,它们通常都带有$前缀,这样做的方式是以便与用户区分开来。来看一个示例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>property</title>
</head>
<body>
<div id="app"> </div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

  var obj = {
name:'eveningwater'
}
var vm = new Vue({
data:obj,
});
//这行代码表示将vue实例挂载到id为app的DOM根节点上,相当于在实例的选项对象中的el选项,即
//el:'#app'
vm.$mount(document.querySelector('#app'))
//数据是相等的
vm.$data === obj;//true
//挂载的根节点
vm.$el === document.querySelector('#app');//true
//以上两个属性都是实例上的属性,接下来还有一个watch即监听方法是实例上的方法
vm.$watch('name',function(oldValue,newValue){
//数据原来的值
console.log(oldValue);
//数据最新的值
console.log(newValue);
})

接下来,可以尝试在浏览器控制台修改name的值,你就会发现watch()方法的作用了,如下图所示:

这个示例可前往具体示例

三.实例生命周期

每个vue实例在被创建的时候都会经历一些初始化的过程,这其中提供了一些生命周期钩子函数,这些钩子函数代表不同的生命周期阶段,这些钩子函数的this就代表调用它的那个实例。对于生命周期,有一张图:

你不需要立即这张图所代表的含义,我们来看一个示例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>vue life cycle</title>
</head>
<body>
<div id="app">
<span>vue生命周期</span>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

  var obj = {
name:'eveningwater'
}
var app = new Vue({
data:obj,
beforeCreate:function(){
//此时this指向app这个vue实例,但并不能得到data属性,因此this.name的值是undefined
console.log('实例被创建之前,此时并不能访问实例内的任何属性' + this.name)
}
});

关于生命周期的全部理解,我们需要理解后续的组件知识,再来补充,此处跳过。这个示例可前往具体示例

四.模板语法

vue使用基于HTML的模板语法,在vue的底层是将绑定数据的模板渲染成虚拟DOM,并结合vue的响应式系统,从而减少操作DOM的次数,vue会计算出至少需要渲染多少个组件。

最简单的模板语法莫过于插值了,vue使用的是Mustache语法(也就是双大括号"{{}}")。这个只能对文本进行插值,也就是说无论是字符串还是标签都会被当作字符串渲染。如:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Mustache</title>
</head>
<body>
<div id="app">
<span>{{ greeting }}World!</span>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

 var obj = { greeting:"Hello,"};
var vm = new Vue({
data:obj
});
vm.$mount(document.getElementById('app'));

如此以来Mustache标签就会被data对象上的数据greeting给替代,而且我们无论怎么修改greeting的值,视图都会响应,具体示例

我们还可以使用v-once指令对文本进行一次性插值,换句话说,就是这个指令让插值无法被更新:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Mustache</title>
</head>
<body>
<div id="app">
<span v-once>{{ greeting }}World!</span>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

 var obj = { greeting:"Hello,"};
var vm = new Vue({
data:obj
});
vm.$mount(document.getElementById('app'));

在浏览器控制台中我们输入vm.greeting="stranger!"可以看到视图并没有被更新,这就是这个指令的作用,我们需要注意这个指令对数据造成的影响。具体实例

既然双大括号只能让我插入文本,那要是我们要插入HTML代码,我们应该怎么办呢?v-html这个指令就可以让我们插入真正的HTML代码。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>v-html</title>
</head>
<body>
<div id="app">
<p>{{ message }}</p>
<p v-html="message"></p>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

 var obj = { message:"<span style='color:#f00;'>hello,world!</span>"};
var vm = new Vue({
data:obj
});
vm.$mount(document.getElementById('app'));

页面效果如图所示;

可前往具体示例

关于HTML特性,也就是属性,我们需要用到v-bind指令,例如:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>v-bind</title>
</head>
<body>
<div id="app">
<div v-bind:id="propId">使用v-bind指令给该元素添加id属性</div>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

 var obj = { propId:"myDiv"};
var vm = new Vue({
data:obj
});
vm.$mount(document.getElementById('app'));

打开浏览器控制台,定位到该元素,我们就能看到div元素的id属性为"myDiv",如下图所示:

具体示例

在绑定与元素实际作用相关的属性,比如disabled,这个指令就被暗示为true,在默认值是false,null,undefined,''等转换成false的数据类型时,这个指令甚至不会表现出来。如下例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>v-bind</title>
</head>
<body>
<div id="app">
<button type="button" v-bind:disabled="isDisabled">禁用按钮</button>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

 var obj = { isDisabled:123};
var vm = new Vue({
data:obj
});
vm.$mount(document.getElementById('app'));

这样一来,无论我们怎么点击按钮都没用,因为123被转换成了布尔值true,也就表示按钮已经被禁用了,我们可以打开控制台看到:

你可以尝试这个示例具体示例

在使用模板插值的时候,我们可以使用一些JavaScript表达式。如下例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>expression</title>
</head>
<body>
<div id="app">
<p>{{ number + 1 }}</p>
<p>{{ ok ? "确认" : "取消" }}</p>
<p>{{message.split("").reverse().join("")}}</p>
<div v-bind:id="'my' + elementId">
元素的id为<span :style="{ 'color':color }">myDiv</span>
</div>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

 var obj = {
number: 123,
ok: true,
message: "hello,vue.js!",
elementId: "Div",
color: "red"
};
var vm = new Vue({
data: obj
});
vm.$mount(document.getElementById("app"));

这些JavaScript表达式都会被vue实例作为JavaScript代码解析,具体示例

值得注意的就是有个限制,只能绑定单个表达式,像语句是无法生效的。如下例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>sentence</title>
</head>
<body>
<div id="app">
<p>{{ var number = 1 }}</p>
<p>{{ if(ok){ return '确认'} }}</p>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

  var obj = {
number: 123,
ok: true
};
var vm = new Vue({
data: obj
});
vm.$mount(document.getElementById("app"));

像这样直接使用语句是不行的,浏览器控制台报错,如下图:

不信可以自己试试具体示例

指令(Directives)是带有v-前缀的特殊特性,通常指令的预期值就是单个JavaScript表达式(v-for除外),例如v-ifv-show指令,前者表示DOM节点的插入和删除,后者则是元素的显隐。所以,指令的职责就是根据表达式值的改变,响应式的作用于DOM。现在我们来看两个示例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>v-if</title>
</head>
<body>
<div id="app">
<p v-if="value === 1">{{ value }}</p>
<p v-else-if="value === 2">{{ value }}</p>
<p v-else>{{ value }}</p>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

  var obj = {
value: 1
};
var vm = new Vue({
el: "#app",
data() {
return obj;
}
});

运行在浏览器效果如图:

现在你可以尝试在浏览器控制台更改vm.value = 2vm.value = 3我们就可以看到页面的变化。你也可以狠狠点击此处具体示例查看和编辑。

我们再看v-show的示例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>v-show</title>
</head>
<body>
<div id="app">
<p v-show="value === 1">{{ value }}</p>
<p v-show="value === 2">{{ value }}</p>
<p v-show="value === 3">{{ value }}</p>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

var obj = {
value:1
}
var vm = new Vue({
data:obj
});
vm.$mount(document.querySelector('#app'))

然后查看效果如图:


尝试在控制台修改vm.value = 2vm.value = 3我们就可以看到页面的变化。你也可以狠狠点击具体示例查看。

从上面两个示例的对比,我们就可以看出来v-showv-if指令的区别了,从切换效果来看v-if显然不如v-show,这说明v-if有很大的切换开销,因为每一次切换都要不停的执行删除和插入DOM元素操作,而从渲染效果来看v-if又比v-show要好,v-show只是单纯的改变元素的display属性,而如果我们只想页面存在一个元素之间的切换,那么v-if就比v-show要好,这也说明v-show有很大的渲染开销。

而且v-if还可以结合v-else-ifv-else指令使用,而v-show不能,需要注意的就是v-else必须紧跟v-if或者v-else-if之后。当需要切换多个元素时,我们还可以使用template元素来包含,比如:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>template</title>
</head>
<body>
<div id="app">
<template v-if="value > 1">
<p>{{ value }}</p>
<h1>{{ value }}</h1>
</template>
<template v-else>
<span>{{ value }}</span>
<h2>{{ value }}</h2>
</template>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

  var obj = {
value: 1
};
var vm = new Vue({
el: "#app",
data() {
return obj;
}
});

此时template相当于一个不可见元素,如下图所示:


尝试在控制台修改vm.value = 2就可以看到效果了,你也可以狠狠的点击此处具体示例

对于可复用的元素,我们还可以添加一个key属性,比如:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>key</title>
</head>
<body>
<div id="app">
<template v-if="loginType === 'username'">
<label>username:</label>
<input type="text" key="username" placeholder="enter your username" />
</template>
<template v-else-if="loginType === 'email'">
<label>email:</label>
<input type="text" key="email" placeholder="enter your email" />
</template>
<template v-else>
<label>mobile:</label>
<input type="text" key="mobile" placeholder="enter your mobile" />
</template>
<button type="button" @click="changeType">
toggle login type
</button>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

      var obj = {
loginType: "username",
count:1
};
var vm = new Vue({
el: "#app",
data() {
return obj;
},
methods: {
changeType() {
this.count++;
if (this.count % 3 === 0) {
this.loginType = "username";
} else if (this.count % 3 === 1) {
this.loginType = "email";
} else {
this.loginType = "mobile";
}
}
}
});

效果如图:


你可以狠狠的点击具体示例查看。

从这几个示例我们也可以看出v-if就是惰性,只有当条件为真时,v-if才会开始渲染。值得注意的就是v-ifv-for不建议合在一起使用。来看一个示例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>v-if与v-for</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item,index) in list" v-bind:key="index" v-if="item.active">
<span>{{ item.value }}</span>
</li>
</ul>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

  var obj = {
list:[
{
value:'html',
active:false
},
{
value:'css',
active:false
},
{
value:"javascript",
active:true
}
]
};
var vm = new Vue({
el: "#app",
data() {
return obj;
}
});

虽然以上代码不会报错,但这会造成很大的渲染开销,因为v-for优先级高于v-if,这就造成每次执行v-if指令时总要先执行v-for遍历一遍数据。你可以点击此处具体示例查看。

遇到这种情况,我们可以使用计算属性。如:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>v-if和v-for</title>
</head>
<body>
<div id="app">
<ul v-if="newList">
<li v-for="(item,index) in newList" v-bind:key="index">
<span>{{ item.value }}</span>
</li>
</ul>
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

var obj = {
list: [
{
value: "html",
active: false
},
{
value: "css",
active: false
},
{
value: "javascript",
active: true
}
]
};
var vm = new Vue({
el: "#app",
//先过滤一次数组
computed: {
newList: function() {
return this.list.filter(function(item) {
return item.active;
});
}
},
data() {
return obj;
}
});

如此一来,就减少了渲染开销,你可以狠狠点击这里具体示例查看。

指令的用法还远不止如此,一些指令是可以带参数的,比如v-bind:title,在这里title其实就是被作为参数。基本上HTML5属性都可以被用作参数。比如图片路径的src属性,再比如超链接的href属性,甚至事件的添加也属于参数,如v-on:click中的click其实就是参数。来看一个示例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- 引入vue.js开发版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>param</title>
</head>
<body>
<div id="app">
<a v-bind:href="url">思否</a>
<img :src="src" alt="美女" />
</div>
<script>
//这里写JavaScript代码
</script>
</body>
</html>

js代码:

  var obj = {
url: "https://segmentfault.com/",
src:"http://eveningwater.com/project/imggallary/img/15.jpg"
};
var vm = new Vue({
el: "#app",
data() {
return obj;
}
});

效果如图所示:

你可以点击此处具体示例查看。

v-on指令还可以添加修饰符,v-bindv-on指令还可以缩写成:@。缩写对于我们在繁琐的使用指令的项目当中是一个很不错的帮助。

五.计算属性与侦听器

从零开始学习vue(2)的更多相关文章

  1. 从零开始学习Vue.js,学习笔记

    一.为什么学习vue.js methods 只有纯粹的数据逻辑,而不是去处理 DOM 事件细节. vue.js兼具angular.js和react的优点,并且剔除了他们的缺点 官网:http://cn ...

  2. 从零开始学习Vue(三)

    我们从一个例子来学习组件,vuejs2.0实战:仿豆瓣app项目,创建自定义组件tabbar 这个例子用到其他组件,对于初学者来说,一下子要了解那么多组件的使用,会变得一头雾水.所以我把这个例子改写了 ...

  3. 从零开始学习Vue(一)

    因为最近有个项目的需求是,微信公众号+IOS/Android APP, 界面都很类似. 以往的做法是APP是调用JSON接口,后台只负责提供接口. 而H5,我以前都是用Jquery,用来写手机网站总是 ...

  4. 从零开始学习Vue(四)

    这里引入一个概念SPA(single Page Application), 接着上次的例子,我们在页面底部做了一个Tab的菜单,点击不同的按钮应该是显示不同的内容. 按传统的MVC的思维,我要在Con ...

  5. 从零开始学习Vue(二)

    思维方式的变化 WebForm时代, Aspx.cs 取得数据,绑定到前台的Repeater之类的控件.重新渲染整个HTML页面.就是整个页面不断的刷新;后来微软打了个补丁,推出了AJAX控件,比如U ...

  6. VUE 从零开始 学习笔记 一

    最近刚跳到一个新公司 不是很忙 决定系统的学习一下VUE这个前端框架 参考官方API 好了 废话不多说 开始了 首先 说一下吧 现在很火的主流三大前端框架 Vue,Angular.React, 为什么 ...

  7. ASP.NET从零开始学习EF的增删改查

           ASP.NET从零开始学习EF的增删改查           最近辞职了,但是离真正的离职还有一段时间,趁着这段空档期,总想着写些东西,想来想去,也不是很明确到底想写个啥,但是闲着也是够 ...

  8. 从零开始学习jQuery (五) 事件与事件对象

    本系列文章导航 从零开始学习jQuery (五) 事件与事件对象 一.摘要 事件是脚本编程的灵魂. 所以本章内容也是jQuery学习的重点. 本文将对jQuery中的事件处理以及事件对象进行详细的讲解 ...

  9. 从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式

    本系列文章导航 从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式 一.摘要 本篇文章讲解如何使用jQuery获取和操作元素的属性和CSS样式. 其中DOM属性和元素属性的区分值得 ...

随机推荐

  1. 实现Promise类

    基本使用: let promise = new Promise((resolve, reject) => { // do something if (true) { resolve('succe ...

  2. C# 面向对象1(类和对象的概念)

    1.面向过程-->面向对象 面向过程:面向的是完成这件事儿的过程,强调的是完成这件事儿的动作. 2.面向过程的思想: 以上的,需求一更改,会导致不同的方法,一一去更改. 3.面向对象的思想:找个 ...

  3. 13 UA池和代理池

    一. 下载中间件 框架图 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引擎将请求传递给下载器过程中, 下载中间件可以对请 ...

  4. java中的compareto方法的详细介绍

    java中的compareto方法的详细介绍 Java Comparator接口实例讲解(抽象方法.常用静态/默认方法) 一.java中的compareto方法 1.返回参与比较的前后两个字符串的as ...

  5. 全局捕获异常(适用于SpringMvc,SpringBoot项目)

    @ControllerAdvice 是controller的一个辅助类,最常用的就是作为全局异常处理的切面类.约定了几种可行的返回值,可以返回String字符串,也可以返回ModelAndView,也 ...

  6. shell条件嵌套(if条件语句)

    [注意1]:和Java.PHP等语言不一样,sh的流程控制不可为空,如: 代码如下: <?php if (isset($_GET["q"])) { search(q); } ...

  7. android app 闪屏

    main activity package com.splash.screen; import android.app.Activity; import android.content.Intent; ...

  8. hadoop常见命令

    常用命令 启动Hadoop 进入HADOOP_HOME目录. 执行sh bin/start-all.sh 关闭Hadoop 进入HADOOP_HOME目录. 执行sh bin/stop-all.sh ...

  9. monkey自定义脚本

    自定义脚本稳定性测试 常规的monkey是执行随机的事件流,如果想让monkey测试某个特定的场景,这个时候需要自定义脚本. 用户需要先笔记好脚本再存放在手机上,通过启动monkey -f参数调用脚本 ...

  10. centos7安装es

    #安装java1.8rpm -ivh jdk-8u191-linux-x64.rpm #解压estar -zxvf elasticsearch-6.4.0.tar.gz -C /usr #修改es限制 ...