在这里汇总一下每次都会忘记或者一直没搞懂的知识点,方便自己以后回来看。大家也可以看看就当做是复习啦~
vue的设计模式: MVVMModel-View-ViewModel(简称为MVVM)。MVVM是一种软件设计模式。MVVM源自于MVC设计模式。MVVM的出现促进了前端开发与后端的分离,极大提高了前端的开发效率。MVVM的核心是ViewModel层。他就像一个中转站,负责Model中的数据对象让数据变得更容易管理和使用,该层向上和视图层进行双向数据绑定,向下和Model层通过接口进行数据交互,起到承上启下的作用。1.View层是视图层,也就是用户界面,前端主要由HTML和CSS来构建。View
是代表UI组件,它负责将数据模型转化成UI展现出来。2.ViewModel层视图模型层。ViewModel
是一个同步View和Model的对象。3.ModelModel
是代表数据模型,也可以在Model
中定义数据修改和操作的业务逻辑。
但是上面的解释总是看了也看不懂,所以再去查了别的资料 ↓
在vue中,MVVM模式是怎么实现的: 在vue中,mvvm模式分别是模型层(m)、视图层(v)和ViewModel(vm);mvvm支持双向绑定,当m层数据进行修改时,vm层会检测到变化,并且通知v层进行相应的修改,反之修改v层会通知m层进行修改,实现了视图与模型层的相互解耦。
看到了一个特别好的解释: 在一开始,是通过js来操作DOM, 使用原生API,就像getElementById这类的。后面jQuery横空出世。再后来呢,就是MVVM模式了,model是数据模型, 就是data啊, props之类的数据。view就是视图层,也就是直接呈现在我们面前的页面。现在就通过view-model来把他俩关联起来, model改变了, view呈现的内容也会有所不同,view里的内容发生变化,也会相应地通知model修改数据。
再放一点写得很好的解释:
vue发音同view, vue的api, v-model双向数据绑定 => view-model就是MVVM里面的VM, 通过前文可以通俗的理解为:
v-model => viewModel: 视图层(用户看到的界面view)和数据层(Model模型,vue实例中的data,computed,props等都属于数据层)之间相互”映射”, 即两者任意一个发生改变都会触发对方的变为一致, 只关注数据(model)的变化。
v-if => view-if => if和数据相关, 如果某个数据的结果为true则渲染这个view,否则不渲染, 也是只关注数据(model)的变化。
v-show => view-show => view的显示(diplay)与否和show的布尔值有关, 还是只关注数据(model)的变化。
v-bind => view-bind => 和view相关的数据与另外一个数据进行绑定, 显示的是绑定的数据对应的view, 还是只关注数据(model)的变化。
v-on => view-on => view监听一个事件,即vue实例中对应的方法method, 其实还是通过click等事件,触发数据的改变(data,computed,props),通过数据(model)的变化再反馈给view,还是只关注数据(model)的变化。
v-for => view-for => 把一个数组等容器形式存在的数据(model)以for循环的方式来渲染view, 还是只关注数据(model)的变化。
MVVM中的VM => viewModel 实际上实现了生产力的解放, 应用的设计脱离了固有的DOM结构, 而是我有数据(model)我想把数据展示(view)出来,其他人或服务通过看到这个试图(view)就可以获得数据(model),编辑数据,而不用再拘泥于形式(DOM等),vue框架封装好了这些操作,让编程变得高效简洁,大道至简。
在vue实例中的生命周期, 方法method, computed, watch, filter, props等, 都是用来处理数据, 然后”映射”到视图(view)上, 核心就是数据层(Model), 所以, 用vue这个框架来进行前端的页面的模块化编程, 组件实例的作用域是孤立的, 需要解决的就是不同组件(父子组件和非父子组件)之间的通信问题, 来进行数据传递, 而这个过程会往往伴随这组件实例间的切换, 就有老组件实例的销毁和新组件实例的挂载, 理解组件实例的生命周期对于数据能否精准的传递至关重要。
index.html / App.vue / main.js之间的关系其实对这个地方一直有一点疑惑,不知道这三个文件之间的关系。
首先看看这三个文件长什么样吧:
index.html
app.vue
main.js
(部分个人理解…有错轻喷)浏览器访问项目,最先访问的是index.html文件->main.js->App.vue所以在打开的一瞬间, 页面先出现的内容应该是index.html中的内容<divid="app">如果有内容的话显示这里面的内容(index.html原有的内容)</div>
同时这个id=”app”就是将被挂载的点
main.js 在 webpack 中作为唯一的 entry,然后在 npm run dev
过程中,通过 HtmlWebpackPlugin
自动将通过 main.js 打包的文件插入到了 index.html 中。所以你看不到有哪个地方引用了 main.js,它只出现在了 webpack.base.config.js, 所以index.js中调用了main.js,只是看不到。
main.js中又创建了App实例(createApp(App)),也就是引入我们的App.vue文件作为实例,接下来后面的mount(#app)就是将这个App根实例挂载在以app为id的div里面,将之前的内容替换掉了。上面有一个id为app的挂载点,之后我们的Vue根实例就会挂载到该挂载点上;<divid="app">App组件实例挂载在这里(会替换掉之前index.html的内容)</div>
所以显示的内容就是App组件template中的内容。
生命周期单个组件的生命周期顺序
父子间的生命周期执行顺序
vue2和vue3生命周期的区别
页面生成的过程
原型/原型链
原型 函数是对象,对象都是通过函数创建的。
显式原型:prototype,是每个函数独有的属性。
简单的来说,无论何时,我们创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象包含了通过调用该构造函数所创建的对象共享的属性和方法。其实我们平常的叫法就是指:prototype就是通过该构造函数创建的某个实例的原型对象,但是其实prototype是每个构造函数的属性而已,只能说万物皆对象罢了。 原型对象的优点是:所有的对象实例都可以共享它包含的属性和方法。这一点可以在构造函数里就可以看出来,因为构造函数在函数里面就定义了对象的实例信息,而原型对象可以在任何地方定义属性和方法
隐式原型: __proto__,或者是[[prototype]]是每个对象都具有的属性。
对象的隐式原型=构造函数的显式原型
原型链
现在我写一个构造函数, 并实例化一个对象a
向上查找到最后就是null
总结
原型的作用: 函数Person有一个属性prototype,指向一个对象,对于普通函数来说没多大意义,对于构造函数就有作用了,当使用new操作符时,会把Person.prototype(原型对象)赋值给实例的__proto__(原型实例)属性。JS有一个原型查找机制,把原来定义在实例上的方法,放到原型对象上去,通过构造函数的new操作,会把原型对象赋值给实例的__proto__属性,那么当使用返回的实例去调用某一个方法的时候,如果实例本身上没有,就去自动去实例的__proto__上去查找,这样达到方法的复用,减少内存开销。
原型链的作用: 每一个对象,都有一个原型对象与之关联,这个原型对象它也是一个普通对象,这个普通对象也有自己的原型对象,这样层层递进,就形成了一个链条,这个链条就是原型链。通过原型链可以实现JS的继承,把父类的原型对象赋值给子类的原型,这样子类实例就可以访问父类原型上的方法了。
注册全局属性/方法我们先了解一下vue2的方法:
Vue.prototype.$xxx= () =>{}
Vue.prototype.$xxx = ‘xxx’
使用: this.$xxx
vue3的新方法:
import { createApp } from‘vue’
importAppfrom‘./App.vue’
const app=createApp(App)
app.config.globalProperties.$xxx= “xxx” 使用:
import { getCurrentInstance } from “vue”;
const { appContext } = getCurrentInstance();
const global = appContext.config.globalProperties;
console.log(global);
就能看到全局挂载的属性了
注册全局组件
过去我们注册全局组件的方法:
import XtxSkeleton from './XtxSkeleton.vue'
import ... from ...
....
export default {
install (app) {
// install 方法调用时,会将 Vue 作为参数传入。
app.component(XtxSkeleton.name, XtxSkeleton)
app.component(XtxMore.name, XtxMore)
...
...
(每写一个组件就要在这里全局注册一下)
}
}
然后在main.js中引入,并用use方法使用
import UI from './src/components/library'
Vue.use(UI)
这样会非常麻烦,尤其是在项目中,每一个全局组件都要这样写一遍,那么我们需要一个批量注册全局组件的方法。
// require.context模块导出(返回)一个(require)函数,这个函数能够接收一个参数
export default {
// install 方法调用时,会将 Vue 作为参数传入。
install(app) {
// 批量注册组件
// 使用'require'提供的函数'context',加载某一个目录下的所有'.vue'后缀的文件
// 然后'context'函数会返回一个导入函数'importFn'
// 它有一个属性keys()获取所有的文件路径
// 遍历所有的同时进行全局注册即可
// 如果要挂载原型, 使用app.config.globalProperties方式
// context(目录路径, 是否加载子路径,加载文件的匹配正则)
const importFn = require.context('./', false, /.vue/)
// 导入组件
importFn.keys().forEach(path => {
// 用default导出就.default
const component = importFn(path).default;
// 进行注册
app.component(component.name, component)
})
//
defineDirective(app)
// 挂载Message在原型,这样可以直接this.$message来调用
app.config.globalProperties.$message = Message
}
}
先到这里吧!下一篇继续
声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/235007.html