1994年可以看做前端历史的起点(但是没有前端的叫法)
1995年网景推出了JavaScript
1996年微软推出了iframe标签, 实现了异步的局部加载
1999年W3C发布第四代HTML标准,微软推出用于异步数据传输的 ActiveX(ActiveXObject),各大浏览器厂商模仿实现了 XMLHttpRequest(这是前端的真正的起始)
2006年,XMLHttpRequest被W3C正式纳入标准(这是前端正式的起始)
2006年, 发布了jQuery
2008年问世的谷歌V8引擎,发布H5的草案
2009年发布了第五代JavaScript
2009年 AngularJS 诞生
2010年 backbone.js 诞生
2011年React和Ember诞生
2014年Vue.js诞生
2014年,第五代HTML标准发布
2014年左右,4G时代到来,混合开发(js, android, ios混合开发)
2016年 微信小程序诞生
2017年 微信小程序正式投入运营
2017年底年 微信小游戏
以前的三大框架: angular, react, vue,现在: react, vue, 小程序(微信、支付宝、百度、头条)
以后: js ----- ts (typescript)
把一小部分通用的业务逻辑进行封装,多个封装形成一个模块或者文件,多个模块或者文件就发展成为库或者框架
库:函数库,不会改变编程的思想,如:jQuery。
框架:框架改变了编码思想,代码的整体结构,如:vue,react,小程序等等。
M:model,模型,主要完成业务功能,在数据库相关的项目中,数据库的增删改查属于模型(重点)。
V:view,视图,主要负责数据的显示
C:controller,控制器,主要负责每个业务的核心流程,在项目中体现在路由以及中间件上。
优点:耦合度低、重用性高、生命周期成本低、部署快、可维护性高、有利软件工程化管理
缺点:由于模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难。
MVP是单词Model View Presenter的首字母的缩写,分别表示数据层、视图层、发布层,它是MVC架构的一种演变。作为一种新的模式,
M:model,模型,主要完成业务功能,在数据库相关的项目中,数据库的增删改查属于模型(重点)。
V:view,视图,主要负责数据的显示
P:Presenter负责逻辑的处理,Presenter是从Model中获取数据并提供给View的层,Presenter还负责处理后端任务。
MVP模式与MVC模式的区别:
在MVP中View并不直接使用Model,而在MVC中View可以绕过Controller从直接Model中读取数据。
MVVM是Model-View-ViewModel的缩写,MVVM模式把Presenter改名为ViewModel,基本与MVP模式相似。
唯一区别是:MVVM采用数据双向绑定的方式
MVC衍生出很多变体,MVP,MVVM,MV*, VUE是MVVM,M----V----VM,M数据,V视图, VM是负责M与V相互通信
总结:
架构只是一种思维方式,不管是MVC,MVP,还是MVVM,都只是一种思考问题解决问题的思维,其目的是要解决编程过程中,模块内部高内聚,模块与模块之间低耦合,可维护性,易测试等问题。
架构在于,做好代码的分工,配合。
vscode,webstorm,HbuilderX等等
vue官网](https://cn.vuejs.org/)
作者:尤雨溪 ( 华人 ) , 前Google员工
构建数据驱动的web应用开发框架
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架
Vue 被设计为可以自底向上逐层应用
Vue 的核心库只关注视图层
vue框架的核心:数据驱动和组件化
便于与第三方库或既有项目整合,另一方面,当与单文件组件和 Vue 生态系统支持的库结合使用时,
Vue 也完全能够为复杂的单页应用程序提供驱动。
Vue 不支持 IE8 及以下版本
<body>
V
<div id="app">
要被控制的html{
{key}}
div>
body>
<script src="vue.js">script>
<script>
let vm = new Vue({
el:'#app' //要控制的那片html代码
data:{
key:value}//数据 M
})
script>
1、首先:一个页面包括:结构(HTML模板),表现(css),行为(js)
2、其次:原生JS中的做法:写好HTML的模板和css样式,用js产生数据(逻辑),通过dom的方式控制数据显示在HTML中的那个位置,包括如何显示(DOM的方式改变样式)
3、vue框架:vue中,写好HTML模板,声明式地告知vuejs库,数据显示在何处,在vue对象中处理数据,不用做DOM操作(vuejs库负责)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9pJFGpla-1617256399567)(C:\Users\31759\AppData\Roaming\Typora\typora-user-images\1590679733619.png)]
简单理解,new出来一个Vue的实例,传一堆配置参数,控制一片html
记住一点:有了vue,不用程序员操作dom了,因为,vue把dom操作都做好了。
1、数据驱动
数据驱动,就是通过控制数据的变化来改变(驱动)DOM。背后使用了观察者模式,靠数据的变化来控制页面的变化。这是vue框架的核心,第一周,一定要把数据驱动的思路和编程习惯养成。
2、声明式渲染
声明的意思就是告知,广而告之,即告知程序(Vue框架),在何处渲染什么数据
vue数据绑定是通过 数据劫持和观察者模式 的方式来实现的
1、数据劫持:使用Object.defineProperty();
当你把一个普通的 JavaScript 对象(json)传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
目的是:感知属性的变化。当给属性赋值时,程序是能够感知的(知道的)。如果知道的话,就可以控制属性值的有效范围,也可以改变其它属性的值等。
Object.defineProperty()函数:https://blog.csdn.net/jiang7701037/article/details/102785223
2、观察者模式(发布订阅模式):
目的:当属性发生变化时,其它使用该数据地方跟着变化
功能:
data选项中存储的是页面中需要显示的数据(当然数据可以进行一定的加工后再显示)
是初始化数据的位置,是元数据,是vue实例的一个实例属性,可以接受的数据类型: number/string/boolean/array/json/undefined/null/function
https://cn.vuejs.org/v2/guide/syntax.html#%E6%8F%92%E5%80%BC
功能:可以让html标签里的内容变成动态的(从data中获取), 使用 mustache语法
格式:{ {变量|属性名|表达式|函数调用等等}};
示例:
Message: {
{ msg }}
new Vue({
el:"#app"
msg:"hello 哥们!"
});
这种写法叫作:声明式渲染,即:只需要告知vue,数据在何处显示。
指令名:v-text和v-html
指令是什么? 指令就是html自定义属性
1、v-text="数据名"
功能:可以让html标签里的内容变成动态的(从data中获取),相当于innerText。
示例:
内容:
对比v-text和插值表达式:
1)、当网络速度慢的时候,插值表达式会在页面上出现 { {}} 的显示,但是指令v-text不会,因为,v-text是自定义属性,最多不做解读。
2)、插值表达式更加灵活,可以在标签里面的某个地方显示,但是v-text会让整个标签的内容全部变化。
2、v-html="数据"
非转义输出
功能:可以让html标签里的内容变成动态的(从data中获取),但是不会对内容中的html标签进行转义。相当于innerHTML。
示例:
输出真正的 HTML
内容:
注
双花括号和 v-text(相当于innerText)会将数据解释为普通文本。
v-html相当于innerHTML
指令名:v-bind
功能:可以让html标签里的**属性(名和值)**变成动态的(从data中获取)
1、 属性值动态绑定:v-bind:html属性="数据"
简写 :html属性=“数据”`
2、 属性名动态绑定: v-bind:[属性名]="数据"
示例:
注意: 属性是布尔值 的情况
如果 isButtonDisabled 的值是 null、undefined 或 false,则 disabled 属性甚至不会被包含在渲染出来的 元素中
javascript表达式
在dom里面插入数据,除了可以写原始的数据,还可以使用javascript表达式,
格式:{ {数据+表达式}}
、 v-指令="数据+表达式"
示例:
{
{ number + 1 }}
{
{ ok ? 'YES' : 'NO' }}
{
{ 'i love you'.split('').reverse().join('') }}
注意:
不能使用语句 ,流程控制可以使用三元表达式代替
https://cn.vuejs.org/v2/guide/conditional.html
指令名: v-if 和 v-show
功能:一段dom可以根据条件进行渲染
<div v-show="true">box1div>
<div v-if="false">box2div>
v-show
VS v-if
v-show=“布尔” | v-if=“布尔” | |
---|---|---|
区别 | 操作css | 操作dom |
场景 | 适合频繁切换 | 适合不频繁切换 |
性能消耗 | 初始渲染消耗 | 频繁切换消耗 |
面试题: v-if和 v-show的区别?
相同点:
v-show和 v-if都是 控制 dom元素 的 显示和隐藏 的。
不同点:
1、原理:
v-show是通过控制元素的样式属性display的值,来完成显示和隐藏;
v-if是通过对dom元素的添加和删除,完成显示和隐藏
2、使用场景:由原理(做法)得出使用场景的区别
v-show:使用在dom元素频繁切换的场景
v-if:当dom元素的切换不频繁,可以使用。特别是,首次元素处于隐藏的情况下。
补充: dom的操作(如:创建和删除)是非常耗性能的。为什么?
请看:https://blog.csdn.net/jiang7701037/article/details/98516468
另外,v-if指令还可以结合v-else-if , v-else一起使用。
示例:
宝宝
大宝宝
非宝宝
https://cn.vuejs.org/v2/guide/list.html
指令名: v-for
功能:把数据进行循环显示在html里(渲染)。推荐操作的数据类型:数组、对象、字符串、数字
格式:
用in或者用of都可以:
{
{值}}
{
{值}}
各种情况:
<li v-for="(值,索引) in 数组">{
{值}}/{
{索引}}li>
<li v-for="(对象,索引) in 数组">{
{对象.key}}/{
{索引}}li>
<li v-for="(值,键) in 对象">
<li v-for="(数,索引) in 数字">
<li v-for="(单字符,索引) in 字符">
注意:
空数组,null,undefined不循环
也可以进行循环嵌套
v-for和v-if使用在同一个标签里时,v-for 的优先级比 v-if 更高,即:if是套在for里的,先循环再判断
列表渲染时的key:
在标签里使用属性key,可以唯一标识一个元素。
1、当 Vue.js 用 v-for **更新**已渲染过的元素列表时,它默认用“就地复用”策略。即:**尽量不进行dom元素的操作,只替换文本**。
2、如果你希望进行dom操作,就用key,因为key的目的是为了唯一标识一个元素。
有了key后,可以跟踪每个节点的身份,从而重用和重新排序现有元素
建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
注意:
key不要使用(数组)下标
https://cn.vuejs.org/v2/guide/events.html
指令名:v-on
v-on指令可以简写为:@
功能:绑定事件,vue通过v-on
指令把事件和处理函数进行绑定。
事件处理函数需要放在methods
选项当中去,事件名 不带on,函数可以按照ES5的写法,也可以按照ES6的写法。
格式:
<input type="button" v-on:事件名="javascript代码">
<input type="button" v-on:事件名="方法">
<input type="button" v-on:事件名="方法(参数)" >
<input type="button" v-on:事件名="方法($event,参数)">
new Vue({
methods:{
方法1:function(ev,参数){
业务
这里面的this是vue对象本身
}
方法2(ev,参数){
业务
}
}
})
获取事件对象:
1、 不传参,默认第一个参数,就是事件对象
如:
………………
checkData4(ev){
console.log('事件对象',ev);
},
2、 传参,事件对象需要手动传入(使用官方提供的 $event)
如:
………………
checkData5(str,ev){
console.log('事件对象',ev);
console.log('参数',str);
},
事件处理函数的this:
1、methods选项里的函数里的this是vue对象本身,所以,事件处理函数里的this也是vue对象本身
2、vue提供的选项的值如果是函数时,不可用箭头函数 , 会造成this丢失
事件修饰符
.stop 阻止单击事件继续传播
.prevent 阻止默认行为
.capture 使用事件捕获模式
.self 点到自己时才触发,不是从其它地方(事件流的流)流过来的
.once 只会触发一次
.passive onScroll事件 结束时触发一次,不会频繁触发,移动端使用
注意:
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用
v-on:click.prevent.self
会阻止所有的点击,而v-on:click.self.prevent
只会阻止对元素自身的点击。
按键修饰符
.left 上下左右
.enter 回车
.13 可以使用键码
.ctrl
.alt
.shift
.exact 精准控制,@键盘事件.修饰符1.修饰符2.exact 只有1+2才可触发 1+2+3不可以
.left
.right
.middle 鼠标中键
https://cn.vuejs.org/v2/guide/forms.html
指令名:v-model
功能:视图控制数据,数据也可控制视图,这就是双向绑定,可通过属性+事件绑定实现。而vue中直接提供了一个指令v-model直接完成(v-model 本质上不过是语法糖)。v-model指令只能使用在表单元素上。
不使用v-model完成双向绑定
<input type="text" :value="data数据" v-on:input="changeIptValue">
使用v-model完成双向绑定
<input type="text" v-model="data数据">
其它表单元素的双向绑定
https://cn.vuejs.org/v2/guide/forms.html
表单修饰符
示例:
//需求:
//在下拉框里选择 房间类型(一个房子住多少人)
//动态产生 相应数量的文本框
指令 (Directives) 是带有 v- 前缀的特殊属性。其实就是html标签的里的自定义属性。指令属性的值预期是单个 JavaScript 表达式 (v-for 是例外情况)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM,以下是官方的指令,程序员也可以自定义指令。
常见指令:
指令缩写:
v-bind 缩写 是冒号
v-on 缩写是 @
https://cn.vuejs.org/v2/guide/class-and-style.html
操作样式,就是属性绑定,只不过绑定的属性是class和style,vue在class和style属性上做了加强,还可以使用对象,数组的方式。
绑定姿势
属性值的类型支持
字符串/对象 / 数组
class的属性值(对象的方式)示例:
//
<div class='big-box' :class="{active:isActive,borderbox:isBorder}"></div>
let vm = new Vue({
el: "#app",
data: {
isActive:true,
isBorder:true
}
});
注:vue绑定的class属性和普通的class属性可以共存
class的属性值(数组的方式)示例:
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
style的属性值(对象的方式)示例:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
style的属性值(数组的方式)示例:
<div :style="[obj1,obj2]"> 我是div</div>
data: {
obj1:{
width:"200px",
height:"150px"
},
obj2:{
"background-color":"red"
}
}
示例:
todoList 练习的实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lmQmxH3r-1617256399571)(C:\Users\31759\AppData\Roaming\Typora\typora-user-images\1594365849928.png)]
为了让大家体会vue是数据驱动,根据班级情况尝试扩展如下:
二阶段的运动
全选反选(购物车)
增删改查(或者留言板,或者员工信息)
在vue中,使用某些方式改变数据(model层)时,vue不会把结果呈现在页面上(view层),这就是vue出现的非响应式的情况:
对数组使用了 非变异 (non-mutating method) 方法。因为,没有改变原始数组的内容(如:concat)
修改数组的长度时
修改数组索引上的值(根索引)时
给对象添加新的属性时。
所以,强烈建议:不要修改数组的根键,不要修改数组的长度,可以把未来需要的数据都声明在data选项内部,不要对数组使用非变异的api(数组的变异方法:https://cn.vuejs.org/v2/guide/list.html#%E5%8F%98%E6%9B%B4%E6%96%B9%E6%B3%95)
vue也提供了非响应式问题 解决方案(尽量不要使用)
Vue.set|this.$set(数组, index, value)
Vue.set|this.$set(对象, key, value)
this.$forceUpdate() 强制刷新
不再说了
在模板中放入太多的逻辑会让模板过重且难以维护,而且不好阅读。计算属性computed来帮忙。
计算属性是一个函数,是经过元数据(data里)进一步运算后的数据,计算属性的优点是:当元数据不发生变化时,不会再做计算(即:缓存),只有元数据发生变化时,才做计算。是响应式的,需要在模板中渲染才可调用
语法
//定义
computed:{
计算属性: function(){
return 返回值}
}
//使用
使用: {
{
计算属性}} | v-指令="计算属性"
computed VS methods
methods | computed |
---|---|
方法每次调用都会进行运算 | 基于它们的响应式依赖进行缓存的,如果依赖没有变化,就不再运算 |
一般 | 性能高 |
{ {methodname()}} | { {computedname}} |
适合强制执行和渲染 | 适合做筛选 |
https://cn.vuejs.org/v2/guide/computed.html#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7-vs-%E4%BE%A6%E5%90%AC%E5%B1%9E%E6%80%A7
需要在数据变化时执行异步或开销较大的操作时,这个时候需要属性检测watch。而不要使用计算属性,因为计算属性是同步的(需要立即返回结果)
定义一个选项
watch:{
数据名:'methods的里函数名' //数据名==data的key
数据名:函数体(new,old){
}
数据名:{
handler:fn(new,old){
},
deep: true //深度检测,当侦听的属性是个对象,修改对象的某个键时,就能检测到
immediate: true //首次运行,要不要监听
}
}
示例:
请输入您的问题:<input type="text" v-model.lazy="question" /><br/>
答案:<input type="text" v-model="answer" /><br/>
let vm = new Vue({
el:"#app",
data:{
question:"",
answer:""
},
watch:{
question:function(){
setTimeout(()=>{
this.answer = "吃的是草"
},2000);
}
}
});
深度检测:
<div id="app">
<input type="button" value="测试" @click="fn" />
</div>
let vm = new Vue({
el:"#app",
data:{
person:{
name:"张三疯",
wife:{
name:"梅超风"
}
},
},
methods:{
fn(){
this.person.name="李思峰";
}
},
watch:{
person:{
deep: true, //深度检测,当侦听的属性是个对象,修改对象的某个键时,就能检测到
handler:function(){
console.log("person变了");
},
immediate: true
}
}
});
计算属性 VS 函数 VS 属性检测
计算属性(computed) | 函数(methods) | 属性检测(侦听)(watch) | |
---|---|---|---|
为了显示而用 | 只是处理逻辑,跟普通的函数一样 | 属性变化的检测(相当于事件),当属性的值发生变化时,可以调用函数 | |
依赖模板调用 | √(在模板上调用的) | -(可以在模板使用) | ×(不能在模板上使用) |
是否缓存 | √ | × | √ |
异步 | ×(必须是同步) | √ | √ |
https://cn.vuejs.org/v2/guide/custom-directive.html
系统指令在不够用的情况下,考虑自定义,指令是个函数|对象,用来操作dom的, 里面的this 返回window
Vue.directive('指令名',{
bind:fn(el,binding){
}//指令第一次绑定到元素时调用,此时DOM原始还没有显示在页面上
inserted:fn(el,binding){
} //绑定指令的DOM元素插入到父节点时调用。DOM已经渲染(显示)
update:fn(el,binding){
} //指令所在的元素的model层的数据,view有更新请求时
componentUpdated:fn(el,binding){
} //更新完成时
})
**指令名:**定义指令时,不用加 v- , 使用指令时,加 v-
钩子函数的参数:
钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。
https://cn.vuejs.org/v2/guide/custom-directive.html#%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0
name: 指令名(不带v-)
arg:写在指令名后面的参数,如:v-myfocus:id , arg就是id v-bind:value
expression: 等号后面的表达式,如:v-myfocus:id=“msg+‘1’” ,expression就是msg+‘1’。
value:绑定数据的值,如:v-myfocus:id=“msg+‘1’” , value就是msg的值和1拼接的结果
示例:
//定义指令:
Vue.directive('myfocus', {
inserted: function (el) { // 当被绑定的元素插入到 DOM 中时……
// 聚焦元素
el.focus()
}
})
使用指令
全局定义格式(简写)
Vue.directive('指令名', function(el,binding){ //等价于:bind + update
})
钩子函数的详解:
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
new Vue({
directives:{
指令名 : function(el,binding){
},//简写方式: bind + update
指令名(el,binding){
},
指令名:{
inserted:fn(el,binding){
} //绑定指令的元素插入到父节点时调用 v-focus
bind:fn //指令第一次绑定到元素时调用 v-drag
update:fn //指令所在的元素的model层的数据,view有更新请求时
componentUpdated:fn //更新完成时
}
}
})
示例:
回到顶部
//自定义指令的代码
// 注册一个全局自定义指令 `v-pagetop`
Vue.directive('pagetop', {
inserted: function (el) {
el.onclick = function(){
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
}
})
//使用指令
<div id="app" >
<div v-pagetop
style="width: 100px;height: 100px;background-color:red;">
回到顶部
</div>
</div>
https://cn.vuejs.org/v2/guide/filters.html
对数据在模板中的表现过滤,符合预期,比如数据是0和1,想要表现成对错、成功失败、数据需要过滤器来格式化,vue1.x版本有系统自带过滤器,vue2.x之后完全需要自定义,没有自带过滤器
Vue.filter('过滤器名称',函数(要过滤的元数据,参数1,参数n){
过滤器的功能
return 过滤的结果
})
{
{数据名 | 过滤器名(参数1,参数2)}}
:属性="数据| 过滤器名(参数1,参数2)
filters:{
过滤器名称:函数(要过滤的元数据,参数){
过滤器的功能
return 过滤的结果
} //函数必须要有返回值
}
预购阿里云服务器(ecs云服务器)
链接 -》个人云 -》突发性能型 t5(74/年)-》系统(centOs系统,认准ecs云服务器-》控制台做一下实名认证
域名购买
链接
意义在于分发 Vue 组件中的可复用功能,混入对象就是一个json对象,json对象的属性就是 Vue对象的配置项(data,methods等等,但是没有el)
用法
//定义
let mixin1 = {
data: ...
methods: ...
}
let mixin2 = {
data: ...
methods: ...
}
//组件内部混入 组件选项内
mixins: [mixin1,mixin2] //当混入的键与引入键冲突时以组件内的键为主
//根实例混入
new Vue({
el:"#app",
data:{
msg:"hello"
}
mixins: [mixin1,mixin2]
})
//全局混入:
Vue.mixin(mixin1)
混入普通选项与组件(vue对象)选项合并,遇冲突,以组件(Vue对象)为主。
如果是钩子函数,那么都会调用(混入的钩子先调用)
什么是虚拟DOM(virtual DOM):
所谓的虚拟 dom,也就是我们常说的虚拟节点,它是通过JS的Object对象模拟DOM中的节点,然后再通过特定的render(渲染)方法将其渲染成真实的DOM的节点。
为什么使用虚拟DOM:
使用js操作DOM时(增删改查等等),那么DOM元素的变化自然会引起页面的回流(重排)或者重绘,页面的DOM重绘自然会导致页面性能下降,那么如何尽可能的去减少DOM的操作是框架需要考虑的一个重要问题!
https://blog.csdn.net/jiang7701037/article/details/98516468
真实DOM和虚拟DOM的区别:
虚拟DOM不会进行排版与重绘操作
真实DOM频繁排版与重绘的效率是相当低
虚拟DOM进行频繁修改,然后一次性比较并修改真实DOM中需要改的部分,最后并在真实DOM中进行排版与重绘,减少过多DOM节点排版与重绘损耗
虚拟DOM有效降低的重绘与排版,因为最终与真实DOM比较差异,可以只渲染局部
diff算法:
虚拟DOM,是一种为了尽可能减少页面DOM频繁操作DOM的方式,那么在虚拟DOM中,通过什么方式才能做到呢? 就是Diff算法进行对比
diff算法的原理:
逐步解析newVdom的节点,找到它在oldVdom中的位置,如果找到了就移动对应的DOM元素,如果没找到说明是新增节点,则新建一个节点插入。遍历完成之后如果oldVdom中还有没处理过的节点,则说明这些节点在newVdom中被删除了,删除它们即可。
总结:
1、产生两个虚拟DOM树:newVDom,oldVDom。
2、oldVDom和真实DOM保持一致
3、操作的newVDom
4、操作完毕后,通过diff算法对比newVDom和oldVDom的差异,并在oldVDom标注哪些节点要删除,哪些节点要增加,修改
5、根据oldVDom操作真实的DOM,让真实Dom和oldVDom保持一致
方案1: 登录谷歌应用商城->索引vue-dev-tools->安装->重启浏览器
方案2: https://blog.csdn.net/jiang7701037/article/details/99708017
组件是自定义标签,vueJS提供的组件可以让程序员自定义标签,对页面进行模块化。每个标签里包含HTML,CSS,JS。
vue的组件就是一个vue对象。(vue的两大核心:数据驱动,组件化) 。vue对象的配置项,在vue组件里也可以使用。
配置项如下:
没有el属性。
template:html模板代码,只能有一个根标签
data:必须是个函数
methods:
………………………………
一个完整的标签格式是: <标签名 属性名=“属性值" 事件=”函数“>内容标签名>
第一种:
let 组件变量名= Vue.extend({
template:'{
{msg}},我是header组件'
data:function(){
return {
msg:”hi”
}
},
});
第二种(简化写法):
let 组件变量名={
配置项
};
全局注册:
Vue.component('组件名',组件变量名);
全局注册的组件,在任何vue对象里都可以使用
局部注册:
//在vue对象的components选项里进行注册
new Vue({
el:
components:{
组件名:组件变量名
}
});
局部注册的组件,只能在当前vue对象(组件)里使用。
组件就是自定义标签,所以,使用组件,就跟使用标签是同样的。
<组件名>组件名>
把一个组件的标签写在另外一个组件的template里,就是组件嵌套。
如:
//子组件
let myComSon = {
template:"我是son里的div:{
{msg}}",
data:function(){
return {
msg:"hi:son"
}
}
};
//父组件
let myComParent = {
template:`
我是p:{
{msg}}
`,
data:function(){
return {
msg:"hi"
}
},
components:{
// 局部注册了另外一个组件
"my-com-son":myComSon
}
};
1、 data是个函数(面试题)
一个组件的 data 选项必须是一个函数,且要有返回object,只有这样,每个实例(vue组件对象)就可以维护一份被返回对象的独立的拷贝,否则组件复用时,数据相互影响,也就是说,组件的作用域是独立的。
2、组件模板(html代码)只能有一个根标签
3、组件名不可和html官方的标签名同名
4、组件没有el选项,只有根实例存在el
5、书写:组件名如果小驼峰,那么使用时,用短横线(羊肉串的写法),或者组件名直接都用大驼峰。
使用props来完成组件属性的声明。 props是外部给组件传入的数据。而组件的data是组件内部的数据。
1)、在组件内部增加配置项 props来声明组件里的属性。props里面可以声明多个属性,所以,是个数组。
let myComParent = {
props:["name","sex"], //声明了两个自定义属性
template:`
我是p:{
{msg}}
人的信息:
姓名:{
{name}}
性别:{
{sex}}
`,
data:function(){
return {
msg:"hi"
}
}
};
2)、使用组件时,给属性传入数据:
<my-com-parent name="张三疯他哥" sex="男">my-com-parent>
总结提升认识:
把封装组件和封装函数进行类比:
在组件内部用props声明的属性,相当于封装函数时声明的形参。
使用组件时,相当于调用函数,传递实参。
组件属性和官方标签的属性是同样的道理,所以,给组件的属性也可以v-bind 数据。即:绑定动态的数据
<my-com-parent v-bind:name="name" sex="男">my-com-parent>
如果你想把一个对象的所有属性作为 prop 进行传递,可以使用不带任何参数的 v-bind (即用 v-bind 而不是 v-bind:prop-name)。例如,已知一个 todo 对象:
todo: {
text: 'Learn Vue',
isComplete: false
}
<todo-item v-bind="todo"></todo-item>
等价于:
<todo-item
v-bind:text="todo.text"
v-bind:is-complete="todo.isComplete"
></todo-item>
奇葩情况
在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态
vueJS还提供了对属性类型的验证,包括属性默认值,是否必须等等。这时候,props不能使用数组,而需要使用对象。
如:
props:{
"name":{
type:String