前端的MVVM概念今年来也算是如火如荼,了解完 MVVM的概念,也该找个去尝试下
首先我先试了下 国内小而美的 VUE

  • 试着照着文档敲出入门文件,内容都在注释里
<!doctype html>
<html>

<head>
	<title>VUE 入门</title>
	<style>
		body{display:flex;flex-wrap: wrap;align-items:flex-end;}
		body>div{box-shadow:0 0 3px #000;margin:8px;padding:8px;}
	</style>
</head>

<body>
	<!-- 插值也能插在 dom 的属性里 -->
	<div id="app" content="{{message}}">
		<h4>基础插值</h4>
		<!-- 基础文本插值 -->
		<p>{{message}} </p>
		<!-- 单次插值,之后不再变化 -->
		<p>{{* message}} </p>
		<!-- 可用来输出HTML 只对可信内容进行 HTML 插值 -->
		<p>{{{message}}}</p>
		<!-- 双向绑定 -->
		<!-- 按键修饰符 可绑定按钮事件 也可使用别名以及自己配置别名 -->
		<input type="text" v-model="message" v-on:keyup.13="show" />
	</div>
	
	<!-- 渲染列表 -->
	<div class="list">
		<h4>列表渲染</h4>
		<ul>
			<!-- 直接使用表达式 -->
			<input type="text" v-model="query" placehorder="筛选">
			<li v-if="item.show" id='item{{$index + 1}}' v-for="item in items | filterBy query" track-by="id">
				<h4>{{item.title}}</h4>
				<p>{{item.content}}</p>
				<!-- 遍历对象,不同JS引擎结果不一样 -->
				<h5 v-for="value in item">
					{{$key}} : {{value}}
				</h5>
			</li>
		</ul>
		<!-- v-for 可接收一个整数 -->
		<span v-for="n in 10">{{n + 1}}</span>
	</div>
	<!-- 绑定方法 -->
	<div class="show">
		<h4>按钮事件绑定</h4>
		<span>{{message}}</span><br/>
		<input type="text" v-model="name" /><br/>
		<!-- 监听事件 -->
		<!-- 可通过内联JavaScript语句传值. $event -->
		<a href="http://www.baidu.com" v-on:click="showMessage('hello',$event)">点击 alert</a>
		<!-- 
			事件修饰符 v-on:event.stop.prevent.capture.self
			详情查阅 Vue api
		 -->
		<a href="http://www.baidu.com" @click.stop.prevent="editMessage">更改内容</a><br/>
	</div>
	<!-- CLASS 切换 -->
	<div class="toggle">
		<h4>v-show与v-if 以及class切换</h4>
		<style>
			.toggle div.show{height:100px;}
			.toggle div.hide{height:0;}
		</style>
		<!-- checkbox 绑定 -->
		<input type="checkbox" v-model="ok">按钮切换
		<template v-if="ok">
			<button @click="toggle">切换</button>
		</template>
		<template v-else>
			<button @click="colorToggle">颜色切换</button>
		</template>
		<article>
			<section>
				v-show 与 v-if 还是有区别的;
				当 OK为 false 时,
			</section>
			<section v-show="ok">
				v-show 仅仅是将其隐藏;如果频繁切换,可采用v-show.不会进行大量的DOM操作
			</section>
			<section v-if="ok">
				而 v-if 是直接移除该 dom,如果操作很少, v-if 可更好	
			</section>
			
		</article>
		<div :class="{'show':show,'hide':hide}" style="transition:0.4s;" :style="style">	
		</div>
	</div>
	<div class="input">
		<h4>表单绑定</h4>
		<!-- debounce 设置延迟 适合非快速更新视图的情况 -->
		<input v-model="message" debounce="500"/>
		<input type="checkbox" v-model="checked" /><br/>
		<input id="LiLei" type="checkbox" v-model="names" value="LiLei"/>
		<label for="LiLei">LiLei</label>
		<input id="HanMei" type="checkbox" v-model="names" value="HanMei"/>
		<label for="HanMei">HanMei</label>
		<input id="Lucy" type="checkbox" v-model="names" value="Lucy"/>
		<label for="Lucy">Lucy</label>
		<input type="radio" value="one" v-model="radio"/>ONE
		<input type="radio" value="two" v-model="radio"/>TWO
		<select v-model="select" multiple>
			<option selected>1</option>
			<template v-for="n in 5">
				<option>{{n + 2}}</option>
			</template>
		</select>
		<div>
			<p>
				message:{{message}};
			</p>
			<p>
				checkbox:{{checked}};
			</p>
			<p>
				选中的名字有{{names}}
			</p>
			<p>
				单选被选中的值为:{{radio}}
			</p>
			<p>
				select 选中的值为:{{select}}
			</p>
		</div>
	</div>
	<div id="transition" style="min-height:300px;">
		<h4>动画</h4>
		<style>
			.div1{background:#555;width:50px;height:50px;}
			/* 该动画会一直存在 */
			.expand-transition{transition:.4s ease;}
			/* 该样式在进入的时候添加 */
			.expand-enter{height:0;}
			/* 该样式在退出的时候添加 */
			.expand-leave{height:0;}
			.div2{background:red;width:50px;height:50px;}
			.flash-enter{animation:flash-in 1.4s;}
			.flash-leave{animation:flash-out 1.4s;}
			@keyframes flash-out{0%{opacity:1}30%{opacity:0;}40%{opacity:0.2;}100%{opacity:0;}}
			@keyframes flash-in{0%{opacity:0}30%{opacity:1;}40%{opacity:0.2}100%{opacity:1;}}
		</style>
		<button @click="div1Toggle">DIV1 框架消失</button>
		<!-- 指定动画名称 style 应当添加以该 动画名为首的样式 -->
		<div v-if="show" class="div1" :transition="transitionName"></div>
		<div v-if="show" class="div2" transition="flash"></div>
	</div>
</body>
<script src="./vue.js"></script>
<script>
'use strict';
Vue.config.debug = true;
var vue1 = new Vue({
	//	通过ID访问元素
	//	vue1.$el === document.getElementById('app') => true
	el: '#app',
	data: {
		//	每个 Vue 实例都会代理其 data 对象里的所有属性
		//	因此可通过 vue1.message 访问该属性 
		message: 'Hello Vue.js!!!'
	},
	//	生命周期勾子 created compiled ready destroyed 等 详情查阅 Vue api
	created: function() {
		//alert('我被创建了');
	},
	methods: {
		show: function() {
			alert(this.message);
		}
	}
});

//	监视该 实例下的  message 
vue1.$watch('message', function(newVal, oldVal) {
	//	改变后的值
	console.log(newVal);
	//	改变前的值
	console.log(oldVal);
});

var vue2 = new Vue({
	//	通过类名访问元素
	el: '.list',
	data: {
		query:"",
		items: [{
			id: 1,
			title: '标题1',
			content: '内容1',
			show: true,
		}, {
			id: 2,
			title: '标题2',
			content: '内容2',
			show: true,
		}, {
			id: 3,
			title: '标题3',
			content: '内容3',
			show: false
		}]
	},
});
/*
	可对 vue2.items 直接进行数组操作,操作后可触发页面上内容的刷新
	push()
	pop()
	shift()
	unshift()
	splice()
	sort()
	reverse()
	数组替换
	==========================
	以下两种都不会被 vue检测到数组变化
	1. 直接用索引设置元素,如 vm.items[0] = {};
	2. 修改数据的长度,如 vm.items.length = 0。
	可采用 vue2.items.$set(0,{...}) 或  vue2.items.$remove(vue2.items[index])
	去更新数组
*/


var vue3 = new Vue({
	el: '.show',
	data: {
		first_name: 'Li',
		last_name: 'Lei'
	},
	//	TODO
	//	当 first_name 与 last_name 有更改时,都会重新计算
	computed: {
		name: function(event) {
			//	方法内的 this 指向 vue3
			//	event 是原生 DOM 事件 
			return this.first_name + this.last_name;
		},
		fullname: {
			//	getter
			get: function() {
				return this.first_name + this.last_name;
			},
			//	setter
			//	vue3.fullname = 'Han Mei' 即可调用该 setter
			set: function(newValue) {
				var names = newValue.split(' ');
				this.first_name = names[0];
				this.last_name = name[1];
			}
		}
	},
	methods: {
		showMessage: function(msg, event) {
			console.log(msg);
			//	阻止默认事件
			event.preventDefault()
			console.log(event);
			console.log(this.name);
			console.log(vue2.items[0].title);
		},
		editMessage: function() {
			var content = prompt('请输入姓');
			this.first_name = content;
			//	更改 vue1 里的内容
			vue1.message = content;
		}
	}
});

var vue4 = new Vue({
	el: ".toggle",
	data: {
		hide: false,
		style: {
			background: '#555',
			width: '100px'
		},
		styleStatus: true,
		ok: false
	},
	methods: {
		toggle: function() {
			console.log(this.hide)
			if (this.hide) {
				this.hide = false;
			} else {
				this.hide = true;
			}
		},
		colorToggle: function() {
			if (this.styleStatus) {
				this.styleStatus = false;
				this.style = {
					background: 'red',
					width: '200px'
				}
			} else {
				this.styleStatus = true;
				this.style = {
					background: '#555',
					width: '100px'
				};
			}
		},
	},
	computed: {
		show: function() {
			return this.hide ? false : true;
		}
	}
});
/*
	前端发展到现在,一直遵循着 html css 以及 js 分离;
	为了以后维护的时候能更方便;
	然而 Vue 却在 html 里 却将 事件 通过 v-on 严格的绑定在 视图(HTML)上
	我觉的除了官方的解释(模版与JS方法紧耦合,容易查找对应的JS;无需自己再手动 绑定事件与清理dom),
	对使用者也是更加容易了;
	可以将公用的 js 函数 提取出来,
	然后通过不同的 Vue 实例去调用函数.以后有优化JS 时直接去优化该函数,
	而且 视图 和 js 的紧耦合,可以使之更倾向于 组件化
*/

var vue5 = new Vue({
	el: '.input',
	data: {
		message: '',
		checked: '',
		names: [],
		radio: '',
		select: ''
	}
});

var vue6 = new Vue({
	el: '#transition',
	data: {
		show: true,
		//	指定动画名称
		//	若该值为空, 默认采用 v-transition,v-enter,v-leave
		transitionName: 'expand'
	},
	methods: {
		div1Toggle: function() {
			if (this.show) {
				this.show = false;
			} else {
				this.show = true;
			}
		}
	}
});
Vue.transition('expand', {
	beforeEnter: function(el) {
		el.textContent = 'beforeEnter'
	},
	//	enter 及 leave 都可添加回调函数
	enter: function(el,done) {
		el.textContent = 'enter'
		//	enter 后5秒再执行 afterEnter
		setTimeout(done,5000);
	},
	afterEnter: function(el) {
		el.textContent = 'afterEnter'
	},
	enterCancelled: function(el) {
		// handle cancellation
	},

	beforeLeave: function(el) {
		el.textContent = 'beforeLeave'
	},
	leave: function(el) {
		el.textContent = 'leave'
	},
	afterLeave: function(el) {
		el.textContent = 'afterLeave'
	},
	leaveCancelled: function(el) {
		// handle cancellation
	}
});
</script>
</html>


  • 了解完基础用法,开始做个 todo 页面
<!doctype html>
<html>
<head>
	<title> 简单 TODO  </title>
	<style>
		body{background:#d9d9d9;}
		#todo{width:800px;margin:10px auto;background:#fff;box-shadow:0 0 3px rgba(0 0 0 255);transition:.4s ease;padding:16px;}
		#todo>input{width:100%;padding:8px 0;height:32px;outline:none;font-size:18px;border:0;border-bottom:1px solid #d9d9d9;overflow:hidden;}
		.bar{padding:16px 0;}
		#todo>a{width:18%;display:inline-block;}
		h1{text-align:center;}
		ul{list-style:none;width:100%;padding:0;}
		ul>li{height:48px;line-height:48px;overflow:hidden;border-bottom:1px solid #999;}
		li>a{transform:rotate(45deg);font-weight:bold;color:red;float:right;font-size:32px;display:none;}
		li>span{margin-left:32px;transition:.4s;}
		li>input{position:relative;outline:none;}
		li>input:before{content:'';width:18px;height:18px;background:#fff;border:1px solid #d9d9d9;top:-2px;position:absolute;z-index:1;}
		li.checked>input:after{content:'';width:12px;height:6px;border-left:3px solid #999;border-bottom:3px solid #999;top:2px;left:2px;position:absolute;z-index:2;transform:rotate(-45deg);}
		li.checked>span{text-decoration:line-through;color:#555;}
		li:hover>a{display:inline-block;cursor:pointer;}
		.fade-transition{transition:.4s ease}
		.fade-enter,.fade-leave{height:0;}
		.bar>span{color:#999;}
		.bar>span:nth-child(n+2){margin-left:32px;padding:4px 8px;}
		.bar>span:nth-child(n+2):hover{color:#555;transition:.4s;cursor:pointer;}
		.bar>span.active{box-shadow:0 0 4px #222;}
	</style>
</head>
<body>
	<h1>待办事项</h1>
	<div id="todo">
		<input v-model="todo" type="text" v-on:keyup.enter="add" placeholder="请输入待办事项"/>
		<div class="bar">
			<span>共有 {{items.length}} 条代办事项</span>
			<span @click='all' :class="{active:filter.all}">全部事项</span>
			<span @click='undone' :class="{active:filter.undone}">未完成</span>
			<span @click='done' :class="{active:filter.done}">已完成事项</span>
		</div>
		<ul>
			<template v-for="item in items | orderBy 'todoid' | filterBy filter.status ">
				<li transition="fade" :class="{'checked':item.status}">
					<input type="hidden" v-model='item.todoid'>
					<input type="checkbox" @click='status($index)' v-model='item.status'>
					<span>{{item.content}}</span>
					<!-- 获取INDEX -->
					<a v-on:click="remove($index)">+</a>
				</li>
			</template>
		</ul>
	</div>
</body>
<script src="./vue.js"></script>
<script>
	var todoList = new Vue({
	el: '#todo',
	data: {
		test:false,
		filter:{
			all:true,
			done:false,
			undone:false,
			status:'',
		},
		todoid:'1',
		items: [],
		todo:''
	},
	methods: {
		remove: function(index) {
			this.items.splice(index, 1);
		},
		add: function() {
			if (this.todo.trim()) {
				this.items.push({
					content: this.todo,
					todoid:this.todoid,
					status:false
				});
				this.todoid ++ ;
				localStorage.todoId = JSON.stringify(this.todoid);
			}
			this.todo = "";
		},
		status:function(index){
			if(this.items[index].status){
				this.items[index].status = false;
			}else{
				this.items[index].status = true;
			}
		},
		all:function(){
			this.filter = {
				all:true,
				done:false,
				undone:false,
				status:'',
			}
		},
		undone:function(){
			this.filter = {
				all:false,
				done:false,
				undone:true,
				status:false,
			}
		},
		done:function(){
			this.filter = {
				all:false,
				done:true,
				undone:false,
				status:true,
			}
		}
	},
});
todoList.$watch('items',function(newValue,oldValue){
	localStorage.todo = JSON.stringify(newValue);
	//	内部值变化时,也能获取到变化
},{deep:true});
if(localStorage.todo){
	todoList.items = JSON.parse(localStorage.todo);
	todoList.todoid = JSON.parse(localStorage.todoId);
}
</script>
</html>
posted on 2016-05-01 18:28  小玥光  阅读(326)  评论(1编辑  收藏  举报