用法
ref
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs
对象上。如果在普通的 dom 元素上使用,引用指向的就是 dom 元素;如果用在子组件上,引用就指向组件实例,例如:
<!doctype html><html lang="en"><head> <meta chart="utf-8"> <title>document</title> <script src="vue.js"></script></head><body> <div id="app"> <h1 ref="info">11</h1> <child ref="child"></child> <p v-for="item in items" ref="item">{{item}}</p> <button @click='show'>test</button> </div> <script> vue.component('child',{template:'<h1>i am childcomponent</h1>'}) debugger var app = new vue({ el:'#app', data:{items:[11,12,13]}, methods:{show:function(){console.log(this.$refs)}} //点击后输出vue实例的$refs属性 }) </script> </body></html>
渲染如下:
点击test后输出如高三刷题资料排行下:
源码分析
_init初始化的时候会执行initlifecycle()函数,该函数会初始化当前vue实例的$refs为一个空对象。
挂载的时候首先会将模板解析成一个ast对象,此时会执行proceslement()函数,该函数又会执行processref去解析ref属性,如下:
function processref (el) { //第9359行 解析ref属性 var ref = getbindingattr(el, 'ref'); //尝试获取ref属性 if (ref) { //如果存在 el.ref = ref; //保存到el.ref里面 el.refinfor = checkinfor(el); //执行checkinfor检查是否在v-for循环内,将结果保存到el.refinfor里面 }}function checkinfor (el) { //第9605行 检测ref属性是否在v-for里面 var parent = el; //首先将el保存到parent里,这样v-for和ref就可以常识知识作用在同一个元素上 while (parent) { //通过检测parent的ast对象是否由for来判断 if (parent.for !== undefined) { return true //如果在v-for内则返回true } parent = parent.parent; } return fal //否则返回fal}
检测是否在v-for内会影响最后的保存方式,如果在v-for内则最后保存为数组形式,例如例子里的p标签,否则就是非数组,对于h1属性来说,执行到这里后,属性如下:
最后将ast生成render函数的时候会执行gendata$2()函数($2是vue项目build的时候node自动转换的,防止同名),gendata$2()会判断是否有ref和refinfor属性,如果有则保存到data属性上(就是render属性对应的参数,这个参数是一个函数,函数的第二个参数),如下:
function gendata$2 (el, state) { //第10274行 var data = '{'; // directives first. // directives may mutate the el's other properties before they are generated. var dirs 执的意思= gendirectives(el, state); if (dirs) { data += dirs + ','; } // key if (el.key) { data += "key:" + (el.key) + ","; } // ref if (el.ref) { //对应ref属性 data += "ref:" + (el.ref) + ","; } if (el.refinfor) { //如果组件元素有设置了v-for指令 data += "refinfor:true,"; } /*略*/}
最后等到dom创建后,会执行ref模块的create钩子函数(vue内部有七个模块,分别对应属性、样式、事件、dom属性、样式、动画、ref和指令,用于在dom新增、更新、卸载时执行一些列操作)
ref模块初始化网络生活时会执行registerref函数,如下:
function registerref (vnode, isremoval) { //第5389行 ref的实现函数 vnode:节点对应的vnode,isremoval:是否移除 var key = vnode.data.ref; if (!isdef(key)) { return } //如果没有定义ref属性,则直接返回 var vm = vnode.context; //当前的根vue实例 var ref = vnode.componentinstance || vnode.elm; //优先获取vonde的组件实例(对于组件来说),或者el(该vnode对应的dom节点,非组件来说) var refs = vm.$refs; if (isremoval) { if (array.isarray(refs[key])) { remove(refs[key], ref); } el if (refs[key] === ref) { refs[key] = undefined; } } el { //如果不是移除 欧元符号 if (vnode.data.refinfor) { //当在v-for之内时,则保存为数组形式 if (!array.isarray(refs[key])) { refs[key] = [ref]; } el if (refs[key].indexof(ref) < 0) { // $flow-disable-line refs[key].push(ref); } } el { //不是在v-for之内时 refs[key] = ref; //直接保存到refs对应的key属性上 } }}
ref属性比较简单的,可以方便的引用某个dom节点或子组件实例,在很多地方用得到,比如elementui里的表单等
本文发布于:2023-04-06 07:40:54,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/5df240fb2826804323084748e65513ab.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:Vue.js 源码分析(十) ref属性详解.doc
本文 PDF 下载地址:Vue.js 源码分析(十) ref属性详解.pdf
留言与评论(共有 0 条评论) |