vue2面试题11|[2024-11-25]

news/2024/11/30 1:32:20/

1.vue源码-模版解析

javascript"><!DOCTYPE html>
<html>
<head><title></title>
</head>
<body><div id='app'><h1> {{ str }} </h1>{{ str }}
</div></body><script type="text/javascript" src='vue.js'></script>
<script type="text/javascript">new Vue({el:'#app',data: {str:'您好'}
})</script></html>
javascript">class Vue{constructor(options){this.$el = document.querySelector(options.el)this.$data = options.datathis.compile(this.$el)}compile(node){node.childNodes.forEach((item.index) => {// 元素节点if(item.nodeType == 1){this.compile(item)}// 这里是文本节点,如果有{{}}就替换成数据if(item.nodeType == 3){// 正则匹配let reg = /\{\{(.*?)\}\}/glet text = item.textContent// 给节点赋值item.textContent = text.replacce(reg,(match,vmKey) => {vmKey = vmKey.trim()return this.$data[vmKey]})}})}}

 2.vue源码-生命周期

javascript"><!DOCTYPE html>
<html>
<head><title></title>
</head>
<body><div id='app'><h1> {{ str }} </h1>{{ str }}
</div></body><script type="text/javascript" src='vue.js'></script>
<script type="text/javascript">new Vue({el:'#app',data: {str:'您好'},created(){console.log('created',this.$el, this.$data)}beforeCreate(){console.log('beforeCreate',this.$el, this.$data)}mounted(){console.log('mounted',this.$el, this.$data)}beforeMount(){console.log('beforeMount',this.$el, this.$data)}
})</script></html>

得到的结果应该是:

beforeCreate undefined undefined

created undefined data

beforeMount undefined data

mounted  el data

javascript">class Vue{constructor(options){if(typeof options.beforeCreate == 'function'){options.beforeCreate.bind(this)()}// 这是datathis.$data = options.dataif(typeof options.created == 'function'){options.beforeCreate.bind(this)()}if(typeof options.beforeMount == 'function'){options.beforeCreate.bind(this)()}// 这是节点this.$el = document.querySelector(options.el)// 模板渲染this.compile(this.$el)if(typeof options.mounted == 'function'){options.beforeCreate.bind(this)()}}compile(node){node.childNodes.forEach((item.index) => {// 元素节点if(item.nodeType == 1){this.compile(item)}// 这里是文本节点,如果有{{}}就替换成数据if(item.nodeType == 3){// 正则匹配let reg = /\{\{(.*?)\}\}/glet text = item.textContent// 给节点赋值item.textContent = text.replacce(reg,(match,vmKey) => {vmKey = vmKey.trim()return this.$data[vmKey]})}})}}

 3.vue源码-添加事件

javascript"><body><h1>{{str}}</h1><p>{{str}}</p><button @click='btn'>按钮</button>
</body><script type="text/javascript">
new Vue({el: '#app',data:{str:'您好'},methods:{btn(){console.log(this.str)   // undefined}}
})
</script>

注意这里点击按钮,并不能得到str的数据,还是undefined,因为如下图,其中并没有str,要得到str的数据,应该执行this.$data.str,但是对于实际应用中,执行的是this.str,所以还需要改变。

javascript">this.$options = optionscompile(node){node.childNodes.forEach((item.index) => {// 元素节点if(item.nodeType == 1){// 判断元素节点是否绑定了@clickif(item.hasAttribute('@click')){// @click后绑定的属性值let vmKey = item.getAttribute('@click').trim()item.addEventListener('click',(event) => {this.eventFn = this.$options.methods[vmKey].bind(this)this.eventFn(event)})}if(item.childNodes.length>0){this.compile(item)}}// 这里是文本节点,如果有{{}}就替换成数据if(item.nodeType == 3){// 正则匹配let reg = /\{\{(.*?)\}\}/glet text = item.textContent// 给节点赋值item.textContent = text.replacce(reg,(match,vmKey) => {vmKey = vmKey.trim()return this.$data[vmKey]})}})
}

 4.vue源码-data劫持

javascript"><body><h1>{{str}}</h1><p>{{str}}</p><button @click='btn'>按钮</button>
</body><script type="text/javascript">
new Vue({el: '#app',data:{str:'您好'},methods:{btn(){console.log(this.str)   // 123this.str = 456console.log(this.str)   // 456,但是视图并不会改变}}
})
</script>

想要直接通过this.str获得数据,就要在vue外部添加数据

vue{

        $data:{str:123,b:'456'}

        $el

        options

        eventFn

        str:123

        b:'456'

}

注意:其中存在一个问题,就是修改其中的数据,视图并没有改变,若想视图发生改变,就需要使用innerHTML、innerText、textContent

javascript">class Vue{constructor(options){this.$options = optionsthis.proxyData()if(typeof options.beforeCreate == 'function'){options.beforeCreate.bind(this)()}// 这是datathis.$data = options.dataif(typeof options.created == 'function'){options.beforeCreate.bind(this)()}if(typeof options.beforeMount == 'function'){options.beforeCreate.bind(this)()}// 这是节点this.$el = document.querySelector(options.el)// 模板渲染this.compile(this.$el)if(typeof options.mounted == 'function'){options.beforeCreate.bind(this)()}}// 1.给vue大对象赋属性,来自于data中// 2.data中的属性值和vue大对象的属性双向(劫持)proxyData(){for(let key in this.$data){Object.defineProperty(this,key,{get(){return this.$data[key]},set(val){this.$data[key] = val}})}}
}

5.vue源码-更新视图

经过劫持data,发现修改数据之后,会发生数据改变了,但是视图并没有改变

javascript">class Vue{constructor(options){this.$options = optionsthis.$watchEvent = {}if(typeof options.beforeCreate == 'function'){options.beforeCreate.bind(this)()}// 这是datathis.$data = options.datathis.proxyData()this.observe()if(typeof options.created == 'function'){options.beforeCreate.bind(this)()}if(typeof options.beforeMount == 'function'){options.beforeCreate.bind(this)()}// 这是节点this.$el = document.querySelector(options.el)// 模板渲染this.compile(this.$el)if(typeof options.mounted == 'function'){options.beforeCreate.bind(this)()}}// 1.给vue大对象赋属性,来自于data中// 2.data中的属性值和vue大对象的属性双向(劫持)proxyData(){for(let key in this.$data){Object.defineProperty(this,key,{get(){return this.$data[key]},set(val){this.$data[key] = val}})}}// 触发data中的数据发生变化来执行watch中的updateobserve(){for(let key in this.$data){let value = this.$data[key]let that = thisObject.defineProperty(this.$data,key,{get(){return value},set(val){value = valif(that.$watchEvent[key]){that.$watchEvent[key].forEach((item,index) => {item.update()})}}})}}compile(node){node.childNodes.forEach((item.index) => {// 元素节点if(item.nodeType == 1){// 判断元素节点是否绑定了@clickif(item.hasAttribute('@click')){// @click后绑定的属性值let vmKey = item.getAttribute('@click').trim()item.addEventListener('click',(event) => {this.eventFn = this.$options.methods[vmKey].bind(this)this.eventFn(event)})}if(item.childNodes.length>0){this.compile(item)}}// 这里是文本节点,如果有{{}}就替换成数据if(item.nodeType == 3){// 正则匹配let reg = /\{\{(.*?)\}\}/glet text = item.textContent// 给节点赋值item.textContent = text.replacce(reg,(match,vmKey) => {vmKey = vmKey.trim()if(this.hasOwnProperty(vmKey)){let watch = new Watch(this,vmKey,item,'textContent')if(this.$watchEvent[vmKey]){this.$watchEvent[vmKey].push(watch)}else{this.$watchEvent[vmKey] = []this.$watchEvent[vmKey].push(watch)}}return this.$data[vmKey]})}})}
}class Watch{constructor(vm,key,node,attr){// 对象this.vm = vm// 属性名称this.key = key// 节点this.node = node// 改变文本节点内容的字符串this.attr = attr}//执行改变(update)操作update(){this.node[this.attr] = this.vm[this.key]}}


http://www.ppmy.cn/news/1551061.html

相关文章

SM3 Sm4加密算法

一、概述 1、SM3是一种分组消息摘要算法&#xff0c;用于生成数据的哈希值&#xff08;消息摘要&#xff09;&#xff0c;而非直接加密数据。 1.1、 应用场景 数据完整性校验&#xff1a;验证数据在传输或存储过程中是否被篡改。 数字签名&#xff1a;与SM2等算法结合使用&am…

02.ES6(2)

2.10、rest参数 ES6 引入 rest 参数&#xff0c;用于获取函数的实参&#xff0c;用来代替 arguments <script>// ES5 获取实参的方式/* function date(){console.log(arguments);}date(大白,二黑,三孩); */// rest 参数/* function date(...args) {console.log(args)…

数据库期末复习题库

1. Mysql日志功能有哪些? 记录日常操作和错误信息&#xff0c;以便了解Mysql数据库的运行情况&#xff0c;日常操作&#xff0c;错误信息和进行相关的优化。 2. 数据库有哪些备份方法 完全备份&#xff1a;全部都备份一遍表备份&#xff1a;只提取数据库中的数据&#xff0…

最新特性MCP协议客户端复现

参考官方文档 https://modelcontextprotocol.io/quickstart1、客户端 2、 安装uv&#xff0c;一键安装命令&#xff1a; 先使用这个开放策略&#xff0c;否则直接安装失败 &#xff08;我是win11&#xff0c;再powershell&#xff09; Set-ExecutionPolicy RemoteSigned -Sco…

Spring Boot 开发环境搭建详解

下面安装spring boot的详细步骤&#xff0c;涵盖了从安装 JDK 和 Maven 到创建和运行一个 Spring Boot 项目的全过程。 文章目录 1. 安装 JDK步骤 1.1&#xff1a;下载 JDK步骤 1.2&#xff1a;安装 JDK步骤 1.3&#xff1a;配置环境变量 2. 安装 Maven步骤 2.1&#xff1a;下载…

Could not load library libnvrtc.so.11.2. Error: libnvrtc.so.11.2

目录 2. 解决方案 未测试 解决方法 测试ok Could not load library libnvrtc.so.11.2. Error: libnvrtc.so.11.2 torch运行时报错 2. 解决方案 未测试 去PyTorch官网重新下载安装pytorch=2.2。并且看起来pytorch=2.1和pytorch=2.3均不太行。 参考自:Fine-tuning on a V100 …

远离网上的广告和无用信息,自己动手搭建Tipask问答网站

文章目录 前言1.Tipask网站搭建1.1 Tipask网站下载和安装1.2 Tipask网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3 Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试4. 结语 前…

使用ENSP实现OSPF

一、项目拓扑 二、项目实现 1.路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1关闭信息中心 undo info-center enable 进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为1.1.1.1/24 ip address 1.1.1.1 24进入g0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置为2…