一、渐进式框架

二、两个核心点

  1. 响应的数据绑定
    当数据发生改变时,自动更新视图。
    是利用Object.defineProperty中的getter和setter代理数据。
var obj = {};
Object.defineProperty(obj,"a",{
	value:10,  //obj.a值为10
	writable:false,   //表示不可写
	enumerable:false,   //表示不可遍历
	configurable:false,  // 表示不可配置,即不能改变writable:false或者enumerable:false
	get(){               //   当读取obj.a时会自动调用该函数,不管是什么都返回1000
		return 1000;
	},
	set(){         //   当写入obj.a时会自动调用该函数,不管写什么都写入2000
		return 2000;
	}
});

Vue监控的数据变化就是监控的getter和setter得变化。变化就去重新渲染。
2. 视图组件
UI页面映射出一个组件树
组件可重用,可维护性好。
视图与组件的映射

三、虚拟DOM

要改变一个DOM节点,才能把视图重新渲染出来。但这样会发生重排重绘,十分耗费性能。
虚拟DOM就是使用js去模拟一个节点。把js封装出来,变为一个真实的DOM。(使用js对象的嵌套形式模仿出一个html文档),通过底层的算法可以让重排重绘只发生在局部。优化页面。
虚拟DOM工作流程
虚拟DOM

//  模仿实现
function VElement(tagName,prop,children){  //参数为( "",{},[] ) 
	// 判断是不是一个VElement的一个实例
	if ( !(this instanceof VElement) ) {
		return new VElement(tagName,prop,children);
	}
	//  假如用户没有属性prop,就没有给参数prop,进行兼容性处理
	if( Object.prototype.toString.call(prop) === "[object Array]" ){
		children = prop;
		prop = {};
	}
	this.tagName = tagName;
	this.prop = prop;
	this.children = children;
	var count = 0;  //  用于记录虚拟节点个数
	this.children.forEach(function(child,index){
		if(child instanceof VElement){
			// 如果子节点是一个虚拟节点,让总节点数加上子节点的子子节点数
			count += child.count;
		}
		count ++;
	});
	this.count = count;
}
var dom = VElement("div",[VElement("div",["Vue牛逼"])]);
console.log(dom);
// 结果  虚拟DOM   相当于:<div><div>Vue牛逼</div></div>
// VElement {
//   tagName: 'div',
//   prop: {},
//   children: [ VElement { tagName: 'div', prop: {}, children: [Object], count: 1 } ],
//   count: 2 }
VElement.prototype.render = function(){
	//rander函数将虚拟DOM转换为真实DOM
	var dom = document.createElement(this.tagName);
	var children = this.children;
	var prop = this.prop;
	for(var item in prop){
		dom.setAttribute(item,prop[item]);
	}
	children.forEach( function(child,index){
		if(child instanceof VElement){
			var childDom = child.render();
		}else{
			var childDom = document.createTextNode(child);
		}
		dom.appendChild(childDom);
	} );
	return dom;
};
console.log(dom.render());
//  结果
// <div>
//  	<div>Vue牛逼</div>
// </div>

Vue底层时使用深度遍历优先算法转化为dom节点的

四、MVVM模式

M:model 数据模型
V:视图模板
VM:视图模型
VM层是中间层,连接数据模型和视图模板,由Vue实现。由vm代替以前的dom操作,只操作vm层

五、Vue实例

  1. 数据绑定
  2. 计算属性与侦听器
  3. 属性绑定
  4. 条件渲染 v-if v-show
  5. 列表渲染 v-for
  6. 绑定事件 事件修饰符 表单
<!DOCTYPE html>
<html>
<head>
	<title>Vue</title>
</head>
<body>

	<div id="demo">
		{{name}}   <!-- 数据绑定 -->
		{{changeName}}     <!-- 绑定计算属性的changeName -->
		<!-- 通过v-bind:命令绑定属性名 -->
		<!-- 其中class和style比较特殊,要使用数组形式:v-bind:class="[class1]" -->
		<!-- 也可以通过对象的形式:v-bind:class="{class1:classBoolean}",其中class1是class名,而classBoolean才是绑定的变量,为true时才将class1绑定上  (实现添加或删除class) -->
		<span v-bind:data="message" v-bind:id="id">{{name}}</span>
		<!-- v-show 控制节点显示或隐藏,ifshow是绑定的数据,为true时显示,false时内部设为display:none -->
		<!-- v-if也是控制节点显示隐藏,但v-if为false时,是删除节点 -->
		<!-- 频繁切换时,考虑重拍重绘,v-if会更浪费性能 -->
		<div v-show='ifshow'>条件渲染演示</div>
		<!-- items是一个数组,会被v-for遍历,item就是遍历的结果 -->
		<span v-for="item in items">{{item.title}}</span>
		<!-- v-on绑定事件,click为事件名,click1为回调函数,写在methods内 -->
		<button v-on:click="click1">点击</button>
		<!-- 事件修饰符,在事件的回调函数后添加一个.enter,代表只有按下回车键才会触发该事件 -->
		<input type="text" name="" v-on:keyup.enter="keyup1">
		表单,初始化时,会将value的值默认填入input框
		<input type="text" name="" v-model="value">

	</div>		

	<script type="text/javascript" src="https://vuejs.org/js/vue.js"></script>
	<script type="text/javascript">
		//在vue当中,需要一个dom节点挂载Vue,并且vue语法只在此节点内生效
		var vm = new Vue({
			el: "#demo",   // el对应dom节点的id,就把Vue挂载在了dom节点上了
			data:{   // 数据绑定   所有数据都会绑定到实例vm上
				name:"tanjw",
				message : 123,
				id:"demo1",
				ifshow:false,
				items:[{
					title:"18"
				},{
					title:"20"
				}],
				value:123
			},
			//  当name变化时,就会在computed内找一些相关属性
			computed:{  //   计算属性,内部写一些函数
				changeName: function(){  //  当通过控制台改变vm实例name时,changName也会随着变化,监控name的变化
					return "my name is " + this.name;
				}
			},
			methods:{
			// 专门处理异步回调函数
				click1:function(){
					console.log(this);
				},
				keyup1:function(){
					console.log(this.value);
		})
	</script>
</body>
</html>
  1. 生命周期(1最后五分钟)
    生命周期

六、模板

  1. html模板
  2. 字符串模板
  3. render函数
<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>

	<div id="demo">
		{{message}}
		<!-- 双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,需要使用 v-html 指令: -->
		<div v-html="message"></div>  <!-- 这是两层div -->
		<!-- 当使用message时,{{id}}并没有被当做一个绑定数据,而是一个字符串,这就是v-html模板的不足 -->
		<div v-html="message1"></div>  <!-- 这是两层div -->
		<!-- 为弥补次不足,Vue又引入了字符串模板,写在template中 -->
		<!-- 但template的内容会覆盖掉整个被挂载的div -->
	</div>
	
	<!-- 一般会把template单独拿出来,如下 -->
	<script type="x/template" id="template1">
		<div>hello Vue{{id}}</div>
	</script>

	<script type="text/javascript" src="https://vuejs.org/js/vue.js"></script>
	<script type="text/javascript">
		 var vm = new Vue({
		 	el:"#demo",
		 	data:{
		 		message:"<div>hello Vue</div>",  //当绑定的数据是一个节点时,在浏览器并没有被解析成为一个节点,而是一个字符串
		 		//  显而易见,我希望<div>hello Vue</div>要被解析成为一个节点
		 		message1:"<div>hello Vue{{id}}</div>",
		 		id:"true"    
		 	},
		 	template:"#template1",
		 	//  render()函数模板,创建一个虚拟节点
		 	render(creatElement){
		 		var dom = creatElement("",{},[]);
		 		// 或者写成
		 		creatElement("div",{  
		 			attrs:{id:"1"},  
		 			class:{     // class特殊,所以单独拿出来写
		 				vue1:true
		 			},
		 			domProps:{   // 会覆盖掉第三位的[]参数,优先级最高
		 				innerHTML:"任意"
		 			}
		 		},["任意"]);
		 		return dom;     //return dom 就相当于调用了render函数,会将此节点渲染到页面
		 		//  不管以何种方式底层都是调用了render函数
		 		// 但直接使用虽然会增加性能,但无法使用v-if v-for等指令,但可以通过原生JavaScript的if-else和map重写render函数
		 	} 
		 });
	</script>
</body>
</html>
Logo

前往低代码交流专区

更多推荐