个人小总结:1年多没有写博客,感觉很多知识点生疏了,虽然工作上能解决问题,但是当别人问到某个知识点的时候,还是迷迷糊糊的,所以坚持写博客是硬道理的,因为大脑不可能把所有的知识点记住,有可能某一天忘了,但是我们工作上还是会使用,只是理论忘了,所以写博客的好处是可以把之前的东西重新看一遍后会在大脑里面重新浮现起来,特别在面试的时候,别人问你的知识点的时候答不上来那种尴尬,但是平时经常使用到,只是说不出所以来的,因此写博客是最好的思路。

阅读目录

1.vue属性和方法

每个Vue实例都会代理其 data对象里所有的属性。
如下代码:

var data = {
a: 1
};
var vm = new Vue({
data: data
});
console.log(vm);
console.log(vm.a === data.a); // true // 设置属性也会影响到原始数据
vm.a = 2;
console.log(data.a); //
// 反之
data.a = 3;
console.log(vm.a); //
//除了data属性,Vue实例还暴露了一些有用的实例属性与方法。这些属性与方法都有前缀$, 以便与代理的data属性区分。
var data = { a: 1 }
var vm = new Vue({
el: '#container1',
data: data
})
console.log(vm.$data === data) // true
console.log(vm.$el === document.getElementById('container1')) // true
data.a = 5;
// $watch 是一个实例方法
vm.$watch('a', function (newVal, oldVal) {
// 这个回调将在 `vm.a` 改变后调用
console.log(newVal);
console.log(oldVal);
})

1-1. data 必须是函数
通过Vue构造器传入的各种选项大多数都可以在组件里用。 data 是一个例外,它必须是函数。 如下代码Vue 会停止,并在控制台会报错。

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head>
<div id="container1"> <component1></component1>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
var data = { counter: 0 };
// 全局注册
Vue.component('component1', {
template: '<span>{{ message }}</span>',
data: {
message: 'hello'
}
});
new Vue({
el: '#container1'
})
</script>
</html>

data是函数解决该方案
代码如下:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head>
<div id="container1">
<component1></component1>
<component1></component1>
<component1></component1>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
var data = { counter: 0 };
// 全局注册
Vue.component('component1', {
template: '<button v-on:click="counter += 1">{{ counter }}</button>',
// data是一个函数,vue不会报错,但是我们返回给每个组件的实列引用了同一个data对象
data: function() {
return data
}
});
new Vue({
el: '#container1'
})
</script>
</html>

查看效果

由于这三个组件共享了同一个 data , 因此增加一个 counter 会影响所有组件!这不对。我们可以通过为每个组件返回全新的 data 对象来解决这个问题:
代码如下:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head>
<div id="container1">
<component1></component1>
<component1></component1>
<component1></component1>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
// 全局注册
Vue.component('component1', {
template: '<button v-on:click="counter += 1">{{ counter }}</button>',
// data是一个函数,vue不会报错,但是我们返回给每个组件的实列引用了同一个data对象
data: function() {
return {
counter: 0
}
}
});
new Vue({
el: '#container1'
})
</script>
</html>

查看效果

现在每个 counter 都有它自己内部的状态了.

2.理解组件的通信。

一般情况父子组件是这样的关系,组件A在它的模板中使用了组件B,他们之间必然需要相互通信,父组件要给子组件传递数据,子组件需要将它内部发生的事情告知父组件,为了保证父子组件的解耦,可维护性及可重用性。在vue.js中,父组件通过props向下传递数据给子组件,子组件通过events给父组件发送消息。

2-1 使用props传递数据
不能在子组件的模板内直接引用父组件的数据,要让子组件使用父组件的数据,我们需要通过子组件的props选项。
如下代码:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head>
<div id="container1">
<child message="hello!"></child>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
// 全局注册
Vue.component('child', {
// 声明props
props: ['message'],
template: '<span>{{ message }}</span>'
});
new Vue({
el: '#container1'
})
</script>
</html>

结果在页面上会打印 hello。

查看效果

注意: HTML特性是不区分大小写的,所以当使用的不是字符串模板,camelCased(驼峰式) 命名的prop需要转换为相对应的 kebab-case(短横线隔开式)命名:
如下代码:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head>
<div id="container1">
<!-- kebab-case in HTML-->
<child my-message="hello!"></child>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
// 全局注册
Vue.component('child', {
// 声明props
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>'
});
new Vue({
el: '#container1'
})
</script>
</html>

2-2 理解动态prop
在模板中,要动态地绑定父组件的数据到子模板的props,使用v-bind,每当父组件的数据变化时,该变化会传递给子组件。

<div id="container1">
<input v-model='parentMsg' />
<br />
<!-- kebab-case in HTML-->
<child v-bind:my-message="parentMsg"></child>
</div>

使用 v-bind 的缩写语法通常更简单:

<child :my-message="parentMsg"></child>

代码如下:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head>
<div id="container1">
<input v-model='parentMsg' />
<br />
<!-- kebab-case in HTML-->
<child v-bind:my-message="parentMsg"></child>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#container1',
data: {
parentMsg: 'Message'
},
components: {
child: {
props: ['myMessage'],
template: '<span>{{myMessage}}</span>'
}
}
})
</script>
</html>

查看效果

3.理解自定义事件

父组件使用props传递数据给子组件,但是如果子组件需要把数据传回去的话,就需要自定义事件了;
3-1 使用v-on绑定自定义事件
每个vue实例都实现了事件接口,即:
1. 使用 $on(eventName) 监听事件
2. 使用 $emit(eventName) 触发事件
注意: $on 和 $emit 不是 addEventListener 和 dispatchEvent的别名。且 父组件可以在使用组件的地方直接用 v-on 来监听子组件触发的事件。
不能用$on侦听子组件抛出的事件,而必须在模板里直接用v-on绑定,就像以下的例子:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head>
<div id="container1">
<p> {{ total }} </p>
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
Vue.component('button-counter', {
template: '<button v-on:click="increment">{{ counter }}</button>',
data: function() {
return {
counter: 0
}
},
methods: {
increment: function() {
this.counter += 1;
this.$emit('increment');
}
},
})
new Vue({
el: '#container1',
data: {
total: 0
},
methods: {
incrementTotal: function() {
this.total += 1;
}
}
})
</script>
</html>

上面代码: 初始化时候 实例化设置 data: {total: 0}, 设置total为0, 子组件button-counter 默认为0, 当点击子组件的时候调用 increment方法,当前的counter自增1, 然后在子组件触发 $emit('increment')事件,当使用 v-on:increment 会监听到事件后,会调用父组件的incrementTotal方法,因此父组件也自增1.

查看效果

上面代码中 子组件已经和它外部完全解耦了。它所做的只是报告自己的内部事件,至于父组件是否关心则与它无关。

4.理解使用自定义事件的表单输入组件

自定义事件可以用来创建自定义的表单输入组件,使用v-modal来进行数据双向绑定。比如如下代码:

<input v-modal="something" />

上面的代码是下面的语法糖;如下代码:

<input v-bind:value="something" v-on:input="something=$event.target.value" />

因此在创建组件中时,相当于下面的简写;如下代码:

<custom-input v-bind:value="something" v-on:input="something=arguments[0]"></custom-input>

所以要让组件的v-model 生效,必须满足下面的条件:
1. 接受一个value属性。
2. 在有新的value时触发input事件。

如下测试代码:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head>
<div id="container1">
<currency-input v-model="price"></currency-input>
</div>
</body>
<script src="./vue.js"></script>
<script> </script>
<script type="text/javascript">
Vue.component('currency-input', {
template: '\
<span>\
$\
<input\
ref="input"\
v-bind:value="value"\
v-on:input="updateValue($event.target.value)"\
>\
</span>\
',
props: ['value'],
methods: {
// 不是直接更新值,而是使用此方法来对输入值进行格式化和位数限制
updateValue: function (value) {
var formattedValue = value
// 删除两侧的空格符
.trim()
// 保留 2 小数位
.slice(0, value.indexOf('.') + 3)
// 如果值不统一,手动覆盖以保持一致
if (formattedValue !== value) {
this.$refs.input.value = formattedValue
}
// 通过 input 事件发出数值
this.$emit('input', Number(formattedValue))
}
}
});
new Vue({
el: '#container1',
data: {
price: 0
}
})
</script>
</html>

查看效果

5.单个slot

<slot>标签中的任何内容都被视为 备用内容。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有插入的内容时才显示备用内容。
如果<slot>标签中有内容的话,就显示该内容。
比如 my-component 组件有如下代码:

<div class="content">
<h2>this is a component</h2>
<slot>如果没有分发内容,则显示slot中的内容</slot>
<p>asdsadsdad</p>
</div>

父组件有如下代码:

<div id="container1">
<my-component>
<h1>Hello Vue.js</h1>
</my-component>
<my-component></my-component>
</div>

渲染后的结果为:

<div id="container1">
<div class="content">
<h2>this is a component</h2>
<h1>Hello Vue.js</h1>
<p>asdsadsdad</p>
</div>
<div class="content">
<h2>this is a component</h2>
如果没有分发内容,则显示slot中的内容
<p>asdsadsdad</p>
</div>
</div>

所有测试实例代码如下:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head> <div id="container1">
<my-component>
<h1>Hello Vue.js</h1>
</my-component>
<my-component></my-component>
</div> <template id="myComponent">
<div class="content">
<h2>this is a component</h2>
<slot>如果没有分发内容,则显示slot中的内容</slot>
<p>asdsadsdad</p>
</div>
</template> </body>
<script src="./vue.js"></script>
<script type="text/javascript">
Vue.component('my-component', {
template: '#myComponent'
})
new Vue({
el: '#container1'
})
</script>
</html>

查看效果

6.具名slot

<slot> 元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。
如果没有默认的 slot ,这些找不到匹配的内容片段将被抛弃。
比如:假如有一个 my-component 组件,它的模板为:

<template id="myComponent">
<div class='content'>
<header>
<slot name='header'></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name='footer'></slot>
</footer>
</div>
</template>

父组件的模板如下:

<div id="container1">
<h1 slot="header">这里可能是一个页面标题</h1>
<p>主要内容的一个段落</p>
<p>另一个主要段落</p>
<p slot='footer'>这里是底部信息</p>
</div>

页面渲染的结果如下:

<div id="container1">
<h1>这里可能是一个页面标题</h1>
<p>主要内容的一个段落</p>
<p>另一个主要段落</p>
<p>这里是底部信息</p>
</div>

所有的代码如下:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head> <div id="container1">
<h1 slot="header">这里可能是一个页面标题</h1>
<p>主要内容的一个段落</p>
<p>另一个主要段落</p>
<p slot='footer'>这里是底部信息</p>
</div> <template id="myComponent">
<div class='content'>
<header>
<slot name='header'></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name='footer'></slot>
</footer>
</div>
</template> </body>
<script src="./vue.js"></script>
<script type="text/javascript">
Vue.component('my-component', {
template: '#myComponent'
})
new Vue({
el: '#container1'
})
</script>
</html>

查看效果

7.理解作用域插槽(2.1.0新增的)

在slot分发中,无论是单分发还是具名分发,都是父组件替换子组件的数据,或者没有替换,用子组件默认的数据。 但是通过设置作用域槽,就可以改变这种状况,让子组件可以在父组件进行分发时获取自己的数据,至于是什么数据,由子组件决定,这样就能解耦了。
作用域槽通过slot的一个自定义的属性,官方给出的DEMO是text,但也可以是其他,值为暴露的数据。 这个自定义属性已经存放在子组件的prop对象里了。等待着被父组件获取。
怎么获取呢? 在父组件的模板里,使用一个Vue自带的特殊组件<template> ,并在该组件上使用scope属性,值是一个临时的变量,存着的是由子组件传过来的prop对象,获得由子传过来的prop对象。这时候,父组件就可以访问子组件在自定义属性上暴露的数据了。
如下代码:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head>
<div id="container1">
<parent-component></parent-component>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
// 子组件
Vue.component('child-component', {
template: '<ul><slot name="child-ul" v-for="item in rets" v-bind:text="item.name"></slot></ul>',
data: function() {
return {
rets: [
{name: '我是苹果'},
{name: '我是香蕉'},
{name: '我是橘子'}
]
}
}
});
// 父组件
Vue.component('parent-component', {
template: '<child-component><template scope="props" slot="child-ul"><li>{{props.text}}</li></template></child-component>'
})
new Vue({
el: '#container1'
})
</script>
</html>

页面渲染后的代码如下:

<div id="container1">
<ul>
<li>我是苹果</li>
<li>我是香蕉</li>
<li>我是橘子</li>
</ul>
</div>

查看效果

8.理解动态组件

通过使用保留的<component>元素,动态地绑定到它的 is 特性,我们可以让多个组件使用同一个挂载点,并动态的切换。
keep-alive: 如果把切换出去的组件留在内存中,可以保留它的状态或避免重新渲染,为此我们可以添加一个 keep-alive指令参数。
如下实现的tab切换代码:

<!DOCTYPE html>
<html>
<body>
<head>
<title>演示Vue</title>
</head> <h3>动态组件</h3>
<template id="tab-01">
<div>this is tab01</div>
</template>
<template id='tab-02'>
<div>this is tab02</div>
</template>
<template id="tab-03">
<div>this is tab03</div>
</template> <div id="container1">
<!-- 导航栏 -->
<ul>
<li>
<a href="javascript:void(0)" @click="toggleTabs(tab01Text);">{{ tab01Text }}</a>
</li>
<li>
<a href="javascript:void(0)" @click="toggleTabs(tab02Text);">{{ tab02Text }}</a>
</li>
<li>
<a href="javascript:void(0)" @click="toggleTabs(tab03Text);">{{ tab03Text }}</a>
</li>
</ul>
<!-- 点击导航后要切换的内容 -->
<div class='content' style='height: 200px'>
<!-- 如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令参数 -->
<keep-alive>
<component :is="currentView"></component>
</keep-alive>
</div>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
var tab01 = Vue.extend({
template: '#tab-01'
});
var tab02 = Vue.extend({
template: '#tab-02'
});
var tab03 = Vue.extend({
template: '#tab-03'
});
// 新建vue实例
var newVue = new Vue({
el: '#container1',
data: {
tab01Text: "tab01", // 菜单一
tab02Text: "tab02", // 菜单二
tab03Text: "tab03", // 菜单三
currentView: "tab01" // 默认选中的导航栏
},
// 局部注册组件
components: {
tab01: tab01,
tab02: tab02,
tab03: tab03,
},
methods: {
// 绑定tab的切换事件
toggleTabs: function(tabText) {
this.currentView = tabText;
}
}
})
</script>
</html>

查看效果

Vue2 第二天学习的更多相关文章

  1. Vue2基础知识学习

    Vue2基础知识学习 01.初识 new Vue({ el: '#root', //用于指定当前Vue实例为哪个容器服务,值通常为css选择器符 data () { return { } } }); ...

  2. 20145213《Java程序设计》第二周学习总结

    20145213<Java程序设计>第二周学习总结 教材学习内容总结 本周娄老师给的任务是学习教材的第三章--基础语法.其实我觉得还蛮轻松的,因为在翻开厚重的书本,一股熟悉的气息扑面而来, ...

  3. 20145330孙文馨 《Java程序设计》第二周学习总结

    20145330孙文馨第二周学习总结 第二周相比于第一周对java语言有了深一点的了解,也意识到多敲代码才是学习计算机语言的最好方法. 教材内容总结 类型.变量与运算符 *基本类型 整数(short. ...

  4. 20145337 《Java程序设计》第二周学习总结

    20145337 <Java程序设计>第二周学习总结 教材学习内容总结 Java可分基本类型与类类型: 基本类型分整数(short.int.long).字节(byte).浮点数(float ...

  5. 20135328信息安全系统设计基础第二周学习总结(vim、gcc、gdb)

    第三周学习笔记 学习计时:共8小时 读书:1 代码:5 作业:1 博客:7 一.学习目标 熟悉Linux系统下的开发环境 熟悉vi的基本操作 熟悉gcc编译器的基本原理 熟练使用gcc编译器的常用选项 ...

  6. 《Java程序设计》第二周学习总结

    20145224陈颢文<Java程序设计>第二周学习总结 教材学习内容总结 一.类型.变量与运算符 1.类型 整数: 可细分为为short整数(占2字节),int整数(占4字节),long ...

  7. JDBC第二次学习

    脑子太笨,必须得记录下来一些文字,方便回来查询. 这是我的第二次学习JDBC的笔记,看的是传智播客——李勇老师的JDBC系列,已看到第23集. 分析在实际项目中该如何应用JDBC 一个简单用户相关的数 ...

  8. 20155304田宜楠 2006-2007-2 《Java程序设计》第二周学习总结

    20155304田宜楠 2006-2007-2 <Java程序设计>第二周学习总结 教材学习内容总结 一.类型与变量 1.类型 整数: 可细分为为short整数(占2字节),int整数(占 ...

  9. 2017面向对象程序设计(Java)第二周学习总结

    2017面向对象程序设计(Java)第二周学习总结 直系学妹学弟们好!额...不要问我为什么把学妹放前面,我也不知道!我只是你们和蔼可亲的学长一枚而已.也不要问为什么是第二周学习总结而不是第一周,因为 ...

随机推荐

  1. MVC中使用JQuery方式进行异步请求和使用自带方式进行异步请求

    在MCV中使用异步请求可以很很高效地进行前台和后台的数据传递,在这里,笔者为初学者介绍两种在MVC中常用的异步请求处理方式. 在这里,我们通过在一个页面中放置一个按钮来异步获取当前服务器端的系统时间为 ...

  2. (二)在实战中使用Sass和Compass

    第三章 无需计算玩转CSS网格布局 3.1 网格布局介绍 3.2 使用网格布局 3.2.1 术语 术语名 定义 是否涉及HTML标签 列 内容度量的垂直单位 否 容器 构成一个网格布局的HTML元素 ...

  3. canvas-2rect.html

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 【代码笔记】Web-ionic-创建APP的架构

    一,创建app的时候,index.html的主要架构. <!DOCTYPE html> <html> <head> <meta charset="u ...

  5. jquery制作移动端菜单栏左右滑动

    //菜单栏滑动function move_scollX(){ var startPosition, endPosition, distanceX,distanceY; $(".left&qu ...

  6. 03-14_WLST配置现有的Domain

    本文重点: WLST在线模式配置现有的domains. WLST离线模式配置现有的domains.         1.WLST在线模式配置现有的domains 由于和一个活动的domain进行交互, ...

  7. python第八天)——购物车作业优化完成

    发现之前的三级菜单代码有BUG现已经修改过来了 购物车程序:启动程序后,输入用户名密码后,如果是第一次登录,让用户输入工资,然后打印商品列表允许用户根据商品编号购买商品用户选择商品后,检测余额是否够, ...

  8. 位运算符&与、或|、异或^

    &按照二进制位进行运算 如:运算规则:0&0=0: 0&1=0:1&0=0:1&1=1:即:两位同时为“1”,结果才为“1”,否则为0[有0则0] 3& ...

  9. Scrapy爬取遇到的一点点问题

    学了大概一个月Scrapy,自己写了些东东,遇到很多问题,这几天心情也不大好,小媳妇人也不舒服,休假了,自己研究了很久,有些眉目了 利用scrapy 框架爬取慕课网的一些信息 步骤一:新建项目 scr ...

  10. win7系统保护配置现错误“文件名、目录名或卷标语法不正确。(0x8007007B)

    windows7下系统保护功能很是鸡肋,有事会出现一下两个问题: 1.出现错误“文件名.目录名或卷标语法不正确.(0x8007007B) 2.保护设置列表中出现“Windows7_os(c:)(找不到 ...