1、MVVM
(1) 什么是MVVM
MVVM
本质上描述的是一种视图和逻辑之间的数据双向关联关系,专业术语中称为数据双向绑定模式
- 核心:结构分离(视图和数据分离)、双向同步(数据可以自动渲染,页面数据可以自动更新)
MVVM
是一种数据双向绑定模式,核心解决了数据和结构分离、数据双向同步的问题
MVC
是一种编程模式,核心解决了根据用户请求处理不同业务的逻辑问题,主要描述了请求分发
面试题解析:请简单描述一下mvvm
和mvc
你是怎么理解的?
mvvm
和mvc
都是程序开发中的一种编程的设计方式,是一种设计思想
mvvm
主要体现在前端应用中,将页面结构和数据模型进行分离,同时通过中间模块vm
实现数据的双向绑定,提高数据的加载和渲染效率,同时让开发人员的精力主要集中在业务处理上而不是技术同步数据上,提高开发的效率
mvc
主要体现在后端应用中,将客户端请求和对应的业务模块进行规则映射,根据不同的请求分发到不同的业务模块完成数据处理,可以在固定的模式下完成复杂的业务功能处理的软件结构,提高后端应用开发效率
(3) 底层工作原理
Vue
中的一个重要特性就是数据的双向绑定,底层主要是通过数据劫持的方式实现的!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// let myName = "小马"
// 需求1:当我改变myName变量的数据时,请同时打印一句话~数据被改变了
// 需求2:当我读取myName变量的数据时,请同时打印一句话~数据被读取了
// 原生语法中,没有提供可以监听变量数据的事件
// 数据劫持
// ① 临时存储数据的变量
let myNameTemp = "小马"
// ② 数据劫持方式,声明可以监听的变量
// Object.defineProperty() 专门用于数据劫持的函数
// 参数1:挂载的对象
// 参数2:挂载的属性;将一个指定名称的属性挂载到一个指定的对象上
// 下面的代码,将myName变量挂载到window对象上
// 参数3:监听数据变化的对象,包含get()读取函数、set()设置函数
Object.defineProperty(window, 'myName', {
get() {
console.log('有用户读取myName变量的数据了')
return myNameTemp
},
set(val){
console.log('有用户改变myName变量的数据了')
myNameTemp = val
}
})
// 读取数据
console.log(myName) // 同时会触发 get()监听函数
// 设置数据
myName = "DAMU" // 同时会触发set()监听函数
</script>
</body>
</html>
自定义框架:myvue.js
/*
* @Author: mch 2332582158@qq.com
* @Date: 2022-06-08 10:58:44
* @LastEditors: mch 2332582158@qq.com
* @LastEditTime: 2022-06-08 11:13:06
* @FilePath: \code\myvue.js
* @Description:自定义vue框架
*
* Copyright (c) 2022 by mch 2332582158@qq.com, All Rights Reserved.
*/
class MyVue {
constructor(props) {
// 获取挂载节点的DOM对象
this.$el = document.querySelector(props.el)
this._html = this.$el.innerHTML
// 数据劫持的方式,挂载data数据
this.$data = {
...props.data}
for(let key in props.data) {
Object.defineProperty(this, key, {
get() {
return this.$data[key]
},
set(val) {
this.$data[key] = val
// 一旦数据发生更新,从新渲染界面
this.render()
}
})
}
// 挂载methods函数
for(let key in props.methods) {
this[key] = props.methods[key]
}
// 创建好对象,挂载完数据后,调用并渲染页面
this.render()
}
/** 渲染数据的函数 */
render() {
// 定义一个正则表达式,查询需要替换的数据
let reg = /\{\{\s*(.*?\s*\(?\)?)\s*\}\}/ig
// 准备替换数据
let newHtml = this._html.replace(reg, (a, b) => {
console.log(a, b)
if(b.endsWith('()')) {
console.log(b, '这是要执行的函数')
return this[b.substring(0, b.length-2)]()
} else {
console.log(this[b.trim()], '这是要替换的变量')
return this[b.trim()]
}
})
// 替换页面数据
this.$el.innerHTML = newHtml
}
}
自定义框架的使用:demo03自定义框架.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<p>{
{ name }}</p>
<p>{
{ age }}</p>
<p>{
{ intro() }}</p>
</div>
<script src="./myvue.js"></script>
<script>
const app = new MyVue({
el: "#app",
data: {
name: "小马",
age: 20
},
methods: {
intro() {
console.log("姓名:", this.name, ",年龄:", this.age)
return "姓名:" +this.name+",年龄:"+this.age
}
}
})
</script>
</body>
</html>
(5) 疑难解惑
① this.$el
中的$
什么意思?
JS中变量的命名规则:
名称必须由字母、数字、下划线、$组成,数字不能开头
企业项目中开发中,同时用到js和jQuery,变量的约定命名规范:
JavaScript对象:正常命名;或者 变量名称由一个下划线开头,实现了和jQuery对象的差异化管理
let _username = document.getElementById('uname') // _username是一个js对象
jQuery对象:正常命名;或者 变量名称由$符号开头,实现了和普通JS对象的差异化管理
let $username = $('#uname') // $username 是一个jQuery对象
后来的项目开发中,jQuery使用频率开始降低
变量以$符号开头,表示这是一个包含特殊含义的变量