发布网友 发布时间:2024-09-28 23:01
共1个回答
热心网友 时间:2024-11-03 14:42
第二节:Vue实例化1.创建一个Vue实例
通过vue函数创建一个新的vue实例
一个Vue应用由一个通过newVue创建的根Vue实例,以及可嵌套的、可复用的组件树组成的。
我们先看看Vue基本的使用,至于组件我们后面详细的在来探讨
divid="app"!--{{插值表达式,可以赋值取值三元}}--{{msg}}/divscriptsrc="./node_moles\vue\dist\vue.js"/scriptscript//引入vue后会白给你一个Vue构造函数letvm=newVue({//配置对象el:'#app',//告诉vue能管理那个部分,使用的是querySelectordata:{//data中的数据会被vm所代理msg:'helloworld',//可以通过vm.msg取到对应的内容,也可以赋值???}})/script
2.声明式渲染
Vue.js的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM的系统:
2.1.关于{{}}插值表达式
插值表达式,表达式,赋值运算,计算,三元表达式,但是尽量少在这里写逻辑计算
插值:
!--HTML---divid="app"{{message}}/div!--JS---scriptnewVue({el:'#app',data:{messgae:'helloVue!'}})/script
我们已经成功创建了第一个Vue应用!看起来这跟渲染一个字符串模板非常类似,但是Vue在背后做了大量工作。现在数据和DOM已经被建立了关联,所有东西都是响应式的。我们要怎么确认呢?
如果需要确定现在的数据是否已经和DOM建立了关联,形成响应式.
可以将js中的newVue复制给一个全局变量vm.此时vm就是Vue实例化对象,未来可能会用它来搞很多事情,但是最常用到它的时候,是通过this关键字来使用它
varvm=newVue({el:'#app',data:{messgae:'helloVue!'}})
然后在浏览器的js控制台中修改vm.message值,同时页面也会发生改变
在控制台中输入
vm.messge="你好,Vue"
2.2.使用JavaScript表达式
迄今为止,在我们的肆卖模板中,我们一直都只绑定简单的属性键值。但实际上,对于所有的数据绑定,Vue.js都提供了完全的JavaScript表达式支持。
{{number+1}}{{ok?'YES':'NO'}}{{message.split('').reverse().join('')}}divv-bind:id="'list-'+id"/div
这些表达式会在所属Vue实例的数据作用域下作为JavaScript被解析。
示例:
divid="app"!--数字操作--p{{number+2}}/p!--三目运算--p{{ok?'YES':'NO'}}/p!--字符串翻转--p{{message.split('').reverse().join('')?}}/p/divscriptconstvm=newVue({el:"#app",data:{message:'HelloWorld',number:10,ok:true,}})/script
显示结果:
1.png
但是有个*就是,每个绑定双大括号(Mustache语法)里面都只能包含单个表达式
2.3.关于data数据
vue关注的是数据变化,不需要在像裂桥逗以前一样关注DOM的变化
比如我想在2秒之后让页面发生消或变化,我们只需要在2秒后更改数据就可以了
varvm=newVue({el:'#app',data:{msg:'helloworld'}})setTimeout(function(){vm.$data.msg="byeworld"},2000)
关于实例介绍:
示例中vm是Vue的实例对象,
实例对象上有$data属性,其值就是选项对象中data属性值
选项对象就是在实例化Vue时传入的对象
data属性值是一个对象,因此$data也就是这个对象
当通过$data修改msg的值时,也就等于改data中的值,对应是引用类型
因此示例的结果就是:
2秒后data数据中msg的值改变了,又因为Vue是始终在关注着msg这个数据,一旦数据发生变化,就会触发Vue的响应式,继而改变视图显示
2.4再次理解MVVM模式
在上一节讲Vue的mvvm模式的时候就有提到,
Vue实例对象就是vm,data数据就是model,?页面显示的结果就是view
再来看一下mvvm的图
mvvm.jpg
这张图在配合刚才的示例,我们就能很好的理解,当数据Model发生变化以后,Vue就可以通过DataBindings了解到,然后使用新的数据去改变页面显示
至于Vue如何通过DOMListeners监听页面的改变,来改变数据,这个我们之后讲到在说
3.实例上的方法
除了数据属性,Vue选项对象中还暴露了一些有用的属性与方法。在通过实例对象使用选项对象的属性时,属性前面都需要带上前缀$,以便与用户定义的属性区分开来。例如:
vardata={a:1}varvm=newVue({el:'#example',data:data})vm.$data===data//=truevm.$el===document.getElementById('example')//=true
3.1.实例上常用的属性和方法
vm.$attrs//用户获取父组件传递给子组件的属性,(除props,class,style外)vm.$data//vm上的数据vm.$watch//监听vm.$el//当前el元素vm.$set//后加的属性实现响应式vm.$options//vm配置上的所有属性vm.$nextTick(()={})//异步方法,等待渲染dom完成后来获取vmvm.$refs//获取dom元素或者组件实例的引用
其实我们可以创建一个Vue实例,然后在控制台上打印这个实例对象,你会看到很多的属性和方法
constvm=newVue({el:"#app",})
在控制台输入vm
显示结果:
实例属性.png
这里面很多属性,我们暂时不用去关心他,因为随着学习的深入,慢慢都会学习到的.
4.实例化多个vue
我们可以在页面上同时实例化多个Vue,不同的实例接管页面上不同的区域.
看下如下的示例:
##?h1实例化多个Vue对象/h1divid="app-one"h2{{title}}/h2p{{greet}}/p/divdivid="app-two"h2{{title}}/h2p{{greet}}/pbuttonv-on:click="changeTitle"点击改变app-one的h2的内容/button/divscript//?Vue实例varone=newVue({el:'#app-one',data:{title:"vue-app-one的内容"},computed:{greet:function(){return"HelloAppOne"}}})//?Vue实例vartwo=newVue({el:'#app-two',data:{title:"vue-app-two的内容"},methods:{changeTitle:function(){one.title="app-one的内容发生改变了"}},computed:{greet:function(){return"HelloApptwo"}}})/script
Vue事件和方法还没有讲到,先做一个了解即可:
示例分析:
两个实例one和two接管了不同的DOM元素,
点击按钮是在two实例接管的DOM元素中,
所以,当你点击时,只会触发two实例中的方法,也只会改变two实例中的数据
那么问题来了?
能否在two实例中修改one实例中的数据呢,?
答案当然是可以的啦,因为变量one是全局变量,
在two实例化中,就可以通过one变量得到第一个Vue实例化对象,
然后就可以通过实例化对象修改数据,这个可以自己尝试写写.
5.Vue操作DOM元素
虽然Vue是数据驱动的,但是有的时候我们就需要自己手动的获取到DOM元素,对DOM元素进行操作,那么该如何处理呢,
操作DOM元素:
在需要操作的DOM元素中使用ref属性,
ref属性的值是自己随便定义的名字
通过Vue实例的$refs属性获取操作dom元素
divid="app"divref="wuwei"无为/div/divscriptvarvm=newVue({//根实例el:'#app',data:{},mounted(){//dom元素中有多个一样的ref,dom如果不是通过v-for循环出来的,只能获取一个//如果是循环出来的,可以获取多个,获取的是一个数组console.log(this.$refs.wuwei)}});/script
关于示例中$refs属性的解释:
因为可以在多个DOM元素上使用ref.
所以$refs属性获取的是所有具有ref属性的DOM元素的集.
因此要想操作确定的DOM元素就需要在通过当初的ref值获取.
简而言之:就是ref在dom元素上通过this.$refs.自定义名字是获取dom元素
当获取到DOM元素后,然后就可以采用原生的JavaScript对DOM进行操作
注意:
Vue接管的DOM元素之外的元素使用ref是获取不了的,值是undefined
vue生命周期详解vue源码中最终执行生命周期函数都是调用callHook方法,callHook函数的逻辑很简单友山,根据传入的生命周期类型hook,去拿到vm.$options[hook]对应的回调函数数组,然后遍历执行,执行的时候把vm作为函数执行的上下文。
1.newVue(options):创建一个vm实例;
2.mergeOptions(resolveConstructorOptions(vm.constructor),options,vm):合并Vue构造函数里options和传入的options或合并父子的options。比如:在mergeOptions函数中会调用mergeHook方法合并生命周期的钩子函数,mergeHook方法原理是只有父时返回父,只有子时返回数组类型的子。父、子都存在时,将子添加在父的后面返回组合而成的数组。这也是父子均有钩子函数的时候,先执行父的后执行缺埋子的的原因;
3.initLifecycle(vm)、initEvents(vm)、initRender(vm):在创建的vm实例上初始化生命周期、事件、渲染相关的属性;
4.callHook(vm,'beforeCreate'):调用beforeCreate生命周期钩子函数;
5.initInjections(vm)、initState(vm)、initProvide(vm):初始化数据:inject、state、provide。initState的作用是初始化props、data、methods、watch、computed等属性;
6.callHook(vm,'created'):调用created生命周期钩子函数;
7.vm.$mount(vm.$options.el):$mount方法在多个文件中都有定义,如"src/platform/web/entry-runtime-with-compiler.js"、"src/platform/web/runtime/index.js"、"src/platform/weex/runtime/index.js"。因为$mount方法的实现是和平台、构建方式相关的。以"entry-runtime-with-compiler.js"为例,关键步骤是查看vm.$options中是否有伏告蚂render方法,如果没有则会根据el和template属性确定最终的template字符串,再调用compileToFunctions方法将template字符串转为render方法,最后,调用原先原型上的$mount方法,即开始执行"lifecycle.js"中mountComponent方法;
8.callHook(vm,'beforeMount'):调用beforeMount生命周期钩子函数;
9.vm._render()=vm._update()=vm.__patch__():先执行vm._render方法,即调用createElement生成虚拟DOM,即VNode,每个VNode有children,children每个元素也是?个VNode,这样就形成了?个VNodeTree;再调用vm._update方法进行首次渲染,vm._update方法核心是调用vm.patch方法,这个方法跟vm.$mount一样跟平台相关;vm.patch方法则是根据生成的VNodeTree递归createElm方法创建真实DomTree挂载到Dom上;
10.callHook(vm,'mount'):调用mount生命周期钩子函数:VNodepatch到Dom之后会执行'invokeInsertHook'函数,把insertedVnodeQueue中保存的mount钩子函数执行一遍,insertedVnodeQueue队列中的钩子函数是在根据VNodeTree递归createElm方法创建真实DomTree过程生成的钩子函数顺序队列,因此mounted钩子函数的执行顺序是先子后父;
11.datachanges:数据更新,nextTick中执行flushSchelerQueue方法,该方法会执行watcher队列中的watcher;
12.callHook(vm,'beforeUpdate'):执行watcher时会执行watcher的before方法,即调用beforeUpdate生命周期钩子函数;
13.VirtualDOMre-renderandpatch:重新render生成新的VirtualDOM,并且patch到DOM上;
14.callHook(vm,'updated'):调用updated生命周期钩子函数;
15.vm.$destroy():启动卸销毁过程;
16.callHook(vm,'beforeDestroy'):调用beforeDestroy生命周期钩子函数;
17.Teardownwatchers,childcomponentsandeventlisteners:执行一系列销毁动作,在$destroy的执行过程中,它又会执行vm.__patch__(vm._vnode,null)触发它子组件的销毁钩子函数,这样一层层的递归调用,所以destroyed钩子函数执行顺序是先子后父,和mounted过程一样。
18.callHook(vm,'destroyed'):调用destroyed生命周期钩子函数。
Vue实例理解
Vue实例是通过Vue函数来创建的。可以传入一个选项对象。一个Vue应用通过创建一个根Vue实例,以及可以嵌套和可复用的组件树组成。可以看出,Vue应用实际上是由组件树组成。
Vue实例被创建时,它将data对象中的所有property加入到Vue响应系统中。当这些property属性值发生改变含散时,视图更新为新的值。
定义一个对象,赋值给data对象,修改定义的对象的原始数据,也会改变property的值。
数据改变,视图会重渲染,只有当实例被创建时就以及存在于data中的property才是逗老颤响应的。因此,也就解释了为什么需要在property时定义初始值,这样当发生数据改变会山败更新。
Vue实例自身暴露了一些有用的实例property与方法,它们都有前缀el(表示挂载的元素),vm.watch()等。