vue第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件)
第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件)
#课程目标
- 掌握vue实例的相关属性和方法的含义和使用
- 了解vue的数据响应原理
- 熟悉创建组件,了解全局组件与局部组件的区别,掌握组件的相关注意事项
#知识点
#1.vue实例的相关属性和方法ß
#1.1 属性
Vue实例就是通过new Vue()得到的对象。 我们可以在先在控制台中打印一下vue的实例,如图:

- app.$data 对应组件中data的值
- app.$props 对应组件中props的值
- app.$el vue实例挂载到的节点
- app.$options 用于当前 Vue 实例的初始化选项。需要在选项中包含自定义属性时会有用处
- app.$parent 父实例,如果当前实例有的话。
- app.$root 当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
- app.$children
<item><div></div></item>item的$children就是div - app.$slots 用来访问被插槽分发的内容
- app.$scopedSlots 用来访问作用域插槽
- app.$refs 一个对象,持有注册过
ref特性 的所有 DOM 元素和组件实例。(用于所有添加过ref属性的元素) - app.$isServer 当前 Vue 实例是否运行于服务器
- app.$attrs 包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (
class和style除外)。 - app.$listeners 包含了父作用域中的 (不含
.native修饰器的)v-on事件监听器。它可以通过v-on="$listeners"传入内部组件——在创建更高层次的组件时非常有用。
在这里主要看这4个属性:
- app.$el ===> vue实例挂载到的节点
- app.$data ===> 对应组件中data的值
- app.$options ===> 用于当前 Vue 实例的初始化选项。需要在选项中包含自定义属性时会有用处
- app.$refs ===> 用于所有添加过ref属性的元素
app.$options方法实例:
var app = new Vue({
el: "#app",
data:{
msg:"hello vue!"
},
name:"xiaoming",
age:23,
showMe:function(){
console.log("自定义showMe方法");
}
})
console.log(app.$el); // 获得了el的dom对象
console.log(app.$data); // 获得了data对象
console.log(app.$options); // 获得了自定义的属性对象
console.log(app.$options.name); // 获得了自定义的name,值为:xiaoming
app.$options.showMe(); // 获取了自定义的show方法,并执行值为:自定义showMe方法
app.$refs方法实例:
<div id="app">
<div class="div1" ref="divDom"></div>
<p class="p1" ref="pDom"></p>
</div>
var app = new Vue({
el: "#app",
data:{
}
})
console.log(app.$refs) // 获取到了所有带有 ref的dom标签
console.log(app.$refs.pDom) // 获取到了带有ref属性并且值为pDom的标签
console.log(app.$refs.divDom) // 获取到了带有ref属性并且值为divDom的标签
// 可以这样设置
app.$refs.pDom.style.color = "pink";
#1.2方法
而vue实例中的方法,可以展开__proto__对象,如图,可以看见:

其中,以下几个就是vue实例中的方法($emit,$on,$off,等等的方法之后课程再介绍):
- app.$mount() 手动挂载vue实例
- app.$destroy() 用于销毁vue实例
- app.$nextTick(callback) 用于数据更改,dom更新完成后执行
- app.set(object,key,value) 动态地为对象新增一个值,并且页面上的模版会实时地动态更新渲染值
- app.$delete(object, key) 删除一个已有的属性,dom也会实时更新
- app.$watch(data, callback(newValue,oldValue), [option]) 监视数据的变化
app.$mount()===>手动挂载vue实例 有两种写法分别为:
//第一种
var vm = new Vue({
// el: "#app", // 注释了挂载到dom对象
data:{
msg:"hello vue!"
}
})
vm.$mount("#app"); // 这样也可以挂载到dom对象
//第二种
var vm = new Vue({
// el: "#app", // 注释了挂载到dom对象
data:{
msg:"hello vue!"
}
}).$mount("#app"); // 在实例最后调用$mount("需要挂载的dom");
app.$nextTick(callback) ===> 用于数据更改,dom更新完成后执行
var vm = new Vue({
// el: "#app", // 注释了挂载到dom对象
data:{
msg:"hello vue!"
}
}).$mount("#app");
vm.msg = "hello world!"; // 这里更改了数据
// 这里获取DOM的内容为:hello vue!,因为dom数据还没更新完成
console.log(vm.$refs.pDom.innerHTML);
// 这里获取DOM的内容为:hello world!,因为dom数据已经更新完成
vm.$nextTick(function(){
console.log(vm.$refs.pDom.innerHTML);
});
app.set(object,key,value) 实例用法
<div class="box" id="app">
<button @click="addFn">添加一个属性</button>
{{user.name}}
{{user.num}}
</div>
<script>
var vm = new Vue({
el: "#app",
data:{
user:{
name:"yang"
}
},
methods:{
addFn:function(){
//this.user.num = "9527"; // 页面上的模版无法渲染
//console.log(this.user); // 能打印出来,但是也页面上的模版未渲染出来
// this.$set(this.user, "num", "9527"); // 页面上的模版渲染出来了值
Vue.set(this.user, "num", "9527") //vm.$set 的全局写法
}
}
})
</script>
app.$delete 实例用法
<div class="box" id="app">
<button @click="deleteFn">删除一个属性</button>
{{user.name}}
</div>
<script>
var vm = new Vue({
el: "#app",
data:{
user:{
name:"yang"
}
},
methods:{
deleteFn: function(){
// vm.$delete(this.user, "name"); // 删除页面上已有的一个属性,dom也会实时更新
Vue.delete(this.user, "name"); // vm.$delete 全局写法
}
}
})
</script>
vm.$watch(data, callback(newValue,oldValue), [option]) 实例用法
<input type="text" v-model="msg"> // 绑定 vm.$watch 写法1
{{msg}}
<input type="text" v-model="id"> // 绑定 watch 写法2
{{id}}
<input type="text" v-model="user.name"> // 绑定 watch 写法2
{{user.name}}
var vm = new Vue({
el:"#app",
data:{
msg:"hello vue!",
id:"1001",
user:{
name:"yang"
}
},
/* watch:{ // 写法2:vue实例提供的一个选项 - 普通监视数据变化
id:function(newValue, oldValue){
console.log("id更改之后的值"+ newValue +",id更改之前的值"+ oldValue);
}
} */
watch:{ // 写法2:vue实例提供的一个选项 - 深度监视对象数据变化
user:{
handler:function(newValue, oldValue){
console.log("user更改之后的值"+ newValue +",user更改之前的值"+ oldValue);
},
deep: true
}
}
})
// 写法1:vue实例提供的$watch方法 - 普通监视数据变化
vm.$watch("msg",function(newValue, oldValue){
console.log("msg更改之后的值"+ newValue +",msg更改之前的值"+ oldValue);
})
// 写法1:vue实例提供的$watch方法 - 深度监视对象数据变化
vm.$watch("user",function(newValue, oldValue){
// 监视一个对象后,这里的newValue 和 oldValue将会指向同一指针,也就是指向了同一个值,更改前后值会一样
console.log("user更改之后的值"+ newValue +",user更改之前的值"+ oldValue);
},{
deep:true
})
#2.数据响应原理
现代主流框架均使用一种
数据=>视图的方式,封装了繁琐的dom操作,采用了声明式编程(Declarative Programming)替代了过去的类jquery的命令式编程(Imperative Programming)。

这张图来自vue的官方文档,文档中讲:
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
总结为需要三个模块实现数据响应:
- Observer:也就是vue官方文档第一段提到的使用Object.defineProperty监听数据变化,数据变化则触发setter,并通知订阅者Watcher。
- Watcher:作为Observer和Compile之间通信的桥梁,在自身实例化时往属性订阅器(dep)里面添加自己,待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调。
- Compile: 主要做的事情是解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。
#3.vue 中的组件
#3.1 组件的基本使用
注册组件就是利用Vue.component()方法,先传入一个自定义组件的名字,然后传入这个组件的配置。这种方式创建的组件也叫做全局组件。
Vue.component('mycomponent',{
template: `<div>这是一个自定义全局组件</div>`,
data () {
return {
message: 'hello world'
}
}
})
如上方式,就已经创建了一个自定义组件,然后就可以在Vue实例挂在的DOM元素中使用它。
直接使用Vue.component()创建的组件,所有的Vue实例都可以使用。还可以在某个Vue实例中注册只有自己能使用的组件。也叫做局部组件。
var app = new Vue({
el: '#app',
data: {
},
components: {
'my-component': {
template: `<div>这是一个局部的自定义组件,只能在当前Vue实例中使用</div>`,
}
}
})
具体对比实例:
<div id="app1">
<!—全局组件的使用-->
<mycomponent></mycomponent>
<!—局部组件的使用-->
<my-component></my-component>
</div>
<div id="app2">
<!—全局组件的使用-->
<mycomponent></mycomponent>
<!—局部组件的使用 此处的使用会报错-->
<my-component></my-component>
</div>
<script>
//定义全局组件 每个Vue实例中都能使用
Vue.component('mycomponent',{
template: `<div>这是一个自定义全局组件</div>`,
data () {
return {
message: 'hello world'
}
}
})
var app1 = new Vue({
el: '#app1',
data: {
},
components: {
'my-component': {
template: `<div>这是一个局部的自定义组件,只能在当前Vue实例中使用</div>`,
}
}
})
var app2 = new Vue({
el: '#app2',
data: {
}
})
</script>
#3.2 template模板的要求
注意:组件的模板只能有一个根元素。下面的情况是不允许的。
template: `<div>这是一个局部的自定义组件,只能在当前Vue实例中使用</div>
<button>hello</button>`,
#3.3 组件中的data必须是函数
可以看出,注册组件时传入的配置和创建Vue实例差不多,但也有不同,其中一个就是data属性必须是一个函数。
这是因为如果像Vue实例那样,传入一个对象,由于JS中对象类型的变量实际上保存的是对象的引用,所以当存在多个这样的组件时,会共享数据,导致一个组件中数据的改变会引起其他组件数据的改变。
而使用一个返回对象的函数,每次使用组件都会创建一个新的对象,这样就不会出现共享数据的问题来了。
#3.4 关于DOM模板的解析
当使用 DOM 作为模版时 (例如,将 el 选项挂载到一个已存在的元素上), 你会受到 HTML 的一些限制,因为 Vue 只有在浏览器解析和标准化 HTML 后才能获取模板内容。尤其像这些元素<ul>,<ol>,<table>,<select>限制了能被它包裹的元素,而一些像 <option> 这样的元素只能出现在某些其它元素内部。
通俗点说,虽然 vue 渲染页面可以自定义,非常强大,但是他一定遵从遵循我们的浏览器正常解析,html 正常规范。
在自定义组件中使用这些受限制的元素时会导致一些问题,例如:
<table>
<my-row>...</my-row>
</table>
自定义组件 被认为是无效的内容,因此在渲染的时候会导致错误。
这时应使用特殊的 is 属性:
<table>
<tr is="my-row"></tr>
</table>
又或者是select这样的:
<select>
<my-component></my-component>
</select>
select 内置固定标签 option, 所以不能随意渲染
也就是说,标准HTML中,一些元素中只能放置特定的子元素,另一些元素只能存在于特定的父元素中。比如table中不能放置div,tr的父元素不能div等。所以,当使用自定义标签时,标签名还是那些标签的名字,但是可以在标签的is属性中填写自定义组件的名字。
#4.属性Props
Vue组件通过props属性来声明一个自己的属性,然后父组件就可以往里面传递数据。
Vue.component('mycomponent',{
template: '<div>这是一个自定义组件,父组件传给我的内容是:{{myMessage}}</div>',
props: ['myMessage'],
data () {
return {
message: 'hello world'
}
}
})
然后调用该组件
<div id="app">
<mycomponent my-message="hello"></mycomponent>
</div>
注意,由于HTML特性是不区分大小写的,所以传递属性值时,myMessage应该转换成 kebab-case (短横线隔开式)my-message="hello"。
#授课思路

#案例和作业
使用vue完成一个tab切换

vue第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件)的更多相关文章
- 理解Python中的类对象、实例对象、属性、方法
class Animal(object): # 类对象 age = 0 # 公有类属性 __like = None # 私有类属性 def __init__(self): # 魔法方法 self.na ...
- vue第十六单元(element-ui vue-lazyload 等常用插件)
第十六单元(element-ui vue-lazyload 等常用插件) #课程目标 1.掌握插件的引入方式 2.精通UI框架 3.掌握前端常见的几种效果实现 #知识点 一.elementUI的使用 ...
- day 87 Vue学习六之axios、vuex、脚手架中组件传值
本节目录 一 axios的使用 二 vuex的使用 三 组件传值 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 axios的使用 Axios 是一个基于 promise 的 HT ...
- Vue系列(二):发送Ajax、JSONP请求、Vue生命周期及实例属性和方法、自定义指令与过渡
上一篇:Vue系列(一):简介.起步.常用指令.事件和属性.模板.过滤器 一. 发送AJAX请求 1. 简介 vue本身不支持发送AJAX请求,需要使用vue-resource.axios等插件实现 ...
- day 84 Vue学习六之axios、vuex、脚手架中组件传值
Vue学习六之axios.vuex.脚手架中组件传值 本节目录 一 axios的使用 二 vuex的使用 三 组件传值 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 axios的 ...
- vue第十单元(动态组件 keep-alive(钩子函数) 递归组件(name) 组件命名约定)
第十单元(动态组件 keep-alive(钩子函数) 递归组件(name) 组件命名约定) #课程目标 熟练掌握动态组件的实现 掌握keep-alive缓存组件,以及相应的钩子函数 熟练掌握递归组件, ...
- vue第八单元(组件通信 子父,父子组件通信 自定义事件 事件修饰符 v-model props验证 )
第八单元(组件通信 子父,父子组件通信 自定义事件 事件修饰符 v-model props验证 ) #课程目标 掌握使用props让父组件给子组件传参(重点) 掌握props属性的使用以及prop验证 ...
- vue第七单元(vue的单文件组件形式-单文件组件的加载原理-vue-cli构建的开发环境以及生命周期)
第七单元(vue的单文件组件形式-单文件组件的加载原理-vue-cli构建的开发环境以及生命周期) #课程目标 掌握安装 vue-cli 命令行工具的方法,掌握使用命令行在本地搭建开发环境,使用命令行 ...
- vue第四单元(初识vue-在页面中直接引入vue框架-学习使用vue语法-vue的指令-介绍data用法-methods用法)
第四单元(初识vue-在页面中直接引入vue框架-学习使用vue语法-vue的指令-介绍data用法-methods用法) #课程目标 了解 vue 框架的特点 掌握创建 vue 实例 掌握 data ...
随机推荐
- C#推流RTMP,摄像头、麦克风、桌面、声卡(附源码)
这段时间一直都在研究推流的技术,经过断断续续将近两个月的摸索实践,终于能稳定地推流了. 这个demo的主要功能就是将采集到的摄像头或桌面的视频.以及麦克风或声卡的音频数据推到Nginx-RTMP服务器 ...
- 如何用FL Studio将乐器组合与分层
有过音乐制作经历的小伙伴应该知道,我们在用以FL Studio20为代表的音乐编曲软件制作音乐时,往往需要在同一节奏点添加多种音效,这样可以使音乐听起来更具层次感.正因如此,我们就需要不断添加音符,就 ...
- 在线思维导图Ayoa共享功能使用教程
Ayoa是一个制作思维导图的软件,除了导图制作,小编在使用过程中还发现了一些令人惊喜的功能,这些功能使得Ayoa有了更大的亮点以吸引用户. 下面就为大家简单介绍几个小编认为Ayoa中较为实用的共享功能 ...
- ubuntu解决安装速度问题
速度慢得原因:linux系统很多的软件源链接都是在国外服务器上,由于国内防火墙影响导致下载速度极慢,甚至超时. 解决办法一:购买梯子 这样你就可以快速的下载国外服务器的软件包了,但是你得有个可靠得梯子 ...
- 编曲技巧:使用FL Studio来制作停顿的效果
停顿效果是一种在音乐创作中非常常用的音效,它能起到缓冲的作用,而且能使这段旋律更具节奏感,在比较激情的歌曲中尤为常见.例如知名歌手王力宏演唱的<火力全开>中就使用了停顿效果,为歌曲加了不少 ...
- 现代富文本编辑器Quill的模块化机制
DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师.官方网站:devui.designNg组件库:ng-devui(欢迎S ...
- Springboot整合WebSocket实现网页版聊天,快来围观!
- VisualStudio 编写汇编代码相关设置
VS编写汇编代码方法 新建空项目,不创建解决方案 项目右键,Build Customizations,选择masm 新建源文件,后缀为.ASM 编写代码 .386 ; Tells MASM to us ...
- C++-codeblocks安装
2020-02-15 "Test_leetcode - Debug": The compiler's setup (GNU GCC Compiler) is invalid, so ...
- Django 2版本
django2.0里面的path第一个参数不支持正则,你写什么就匹配,100%精准匹配 django2.0里面的re_path对应着django1.0里面的url 虽然django2.0里面的path ...