天天看点

Vue.js浅学习

主要学习资料为菜鸟教程的vue.js教程。如有错误,还请指出。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
	<title>Vue 练习</title>
	<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
	<!-- vue路由 -->
	<script src="https://cdn.staticfile.org/vue-router/2.7.0/vue-router.min.js"></script>
	<!-- vue Ajax -->
	<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
	<style>
		.class1{
			background: #444;
			color: #eee;
		}
	</style>
</head>
<body>
<!-- 1,vue入门 -->
<div id="vue1">
	<p>1,vue入门</p>
	<p>site:{{site}}</p>
	<!-- v-bind:href 为绑定一个url,也可写成 :href 。v-bind:xxx,均可简写成 :xxx -->
	<p> url:<a v-bind:href="url" target="_blank" rel="external nofollow" >{{urlName}}</a></p>
	<!-- 无参时,可省去括号({{details}}),有参时,不可省去({{details(arg0,arg1)}}) -->
	<p>{{details()}}</p>
</div>
<br>
<script>
	var data = {
	    site:'学习vue.js',
		urlName:'菜鸟教程',
        url:'http://www.runoob.com',
        details:function(){
            return "学习使我快乐!";
        }
	};
	var vm = new Vue({
		el:'#vue1',
		data:data
	});
	//访问的元素
	document.write(vm.$el === document.getElementById('vue1'));//true
	document.write('<br>');
	//引用的对象
	document.write(vm.$data === data);//true
</script>

<!-- 2,vue模板语法 -->
<div id="vue2" >
	<p>2,vue模板语法</p>
	<label>修改颜色<span><input type="checkbox" v-model="use"></span></label>
	<div v-bind:id="'testId-'+id" v-bind:class="{'class1':use}">
		<p><input v-model="message">(过滤首尾空格)<br>{{message | filter1}}</p>
		<p v-if="see" v-bind:hidden="hidden">你看得见我???!(不想看见<input type="checkbox" v-model="hidden">)</p>
		<!-- v-on:click 为绑定一个点击事件。v-on:xxx可简写成 @xxx 。如v-on:change 可简写成 @change -->
		<p v-if="ifnotsee()" v-on:click="displayNow()">click me to display!!!</p>
	</div>
</div>
<script>
	/*
	过滤器1是用Vue.filter进行定义(全局过滤器),2是写在某个实例的filters对象中(局部过滤器)
	 */
	/*Vue.filter('filter1',function(value){
        if(!value) return '';
        return value.trim();
	});*/
	new Vue({
		el:'#vue2',
		data:{
		    id:1,
		    use:false,
			message:"v-bind:class指令",
			see:true,
			hidden:false,
			ifnotsee:function(){
		        return this.hidden == true ? true : false;
			}
		},
		methods:{
            displayNow:function(){
                this.hidden = false;
            }
		},
		filters:{
		    filter1:function(value){
                if(!value) return '';
                return value.trim();
            }
		}
	});
</script>

<!-- 3,vue条件语句 -->
<div id="vue3">
	<p>3,vue条件语句</p>
	<p v-if="seen1">第一个if<button @click="tofalse1()">(first if to false)</button></p>
	<p v-else-if="seen2">第二个if<button @click="tofalse2()">(second if to false)</button></p>
	<p v-else>最后else<button @click="totrue1()">(first if to true)</button></p>
</div>
<script>
	new Vue({
		el:'#vue3',
		data:{
		    seen1:true,
			seen2:false,
			tofalse1:function(){
		        this.seen1 = false;
		        this.seen2 = true;
			},
            tofalse2:function(){
                this.seen2 = false;
            },
            totrue1:function () {
				this.seen1 = true;
            }
		}
	});
</script>

<!-- 4,vue循环语句 -->
<div id="vue4">
	<p>4,vue循环语句</p>
	<div>
		<p>数据循环</p>
		<ol>
			<li v-for="site in sites">
				{{site.value}}
			</li>
		</ol>
	</div>
	<div>
		<p>对象循环</p>
		<ul>
			<li v-for="value in object1">
				{{value}}
			</li>
		</ul>
		<p>其他属性</p>
		<ul>
			<li v-for="(value,key,index) in object2">
				{{(index+1)+"-"+key+"-"+value}}
			</li>
		</ul>
	</div>
	<div>
		<p>整数迭代</p>
		<ul>
			<li v-for="n in 3">
				{{n}}
			</li>
		</ul>
	</div>
</div>
<script>
	var sites = [{value:"tom"},{value:"jerry"},{value:"mike"}];
	var object1 = {name:"tom", sex:"male",age:15};
	var object2 = {name:"jerry", sex:"male", age:14};
	new Vue({
		el:'#vue4',
		data:{
		    sites:sites,
			object1:object1,
			object2:object2
		}
	})
</script>

<!-- 5,vue计算属性 -->
<div id="vue5">
	<p>5,vue计算属性</p>
	<p><input type="text" v-model="message"> </p>
	<p>{{reverseMessage}}</p>
	<p>{{object3}}<span><button @click="runSetter()">运行setter</button></span></p>
</div>
<script>
	var vue5 = new Vue({
		el:'#vue5',
		data:{
		    message:"字符串反转",
			name:"tom",
			enemy:"jerry"
		},
		computed:{//基于依赖缓存,只有相关依赖改变时,才会重新计算。
		    reverseMessage:function(){
		        return this.message.split('').reverse().join('');
			},
			object3:{
		        get:function(){
		            return this.name + ' vs ' +this.enemy;
				},
				set:function(newValue){
		            var names = newValue.split('vs');
		            this.name = names[0];
		            this.enemy = names[1];
				}
			}
		},
		methods:{//函数在重新渲染时,也会重新计算
		    reverseMessage2:function(){
                return this.message.split('').reverse().join('');
			},
			runSetter:function(){//调用此方法将运行object3.setter
		        vue5.object3 = '汤姆vs杰瑞';
			}
		}
	})
</script>

<!-- 6,vue监听属性 -->
<div id="vue6">
	<p>6,vue监听属性</p>
	<p>{{counter}}<span><button @click="counter++">点我自增</button></span></p>
	<p><input type="text" v-model="meter">米<br>
	<input type="text" v-model="kilometer">千米</p>
</div>
<script>
	var vue6 = new Vue({
		el:'#vue6',
		data:{
		    counter:0,
			meter:0,
			kilometer:0
		}
	});
	vue6.$watch('counter', function(){
	    console.log('自增1');
	});
	vue6.$watch('meter', function (val) {
		vue6.kilometer = val/1000;
		vue6.meter = val;
    });
	vue6.$watch('kilometer', function(val){
	    vue6.meter = val*1000;
	    vue6.kilometer = val;
	});
</script>

<!-- 7,vue样式绑定 -->
<div id="vue7">
	<p>7,vue样式绑定</p>
	<p :style="[colorAndSize, fontweight]">学习使我快乐!</p>
</div>
<script>
	new Vue({
		el:'#vue7',
		data:{
		    colorAndSize:{
		        color:'red',
				fontSize:'30px'
			},
			fontweight:{
		        'font-weight':'bold'
			}
		}
	})
</script>

<!-- 8,vue事件处理器 -->
<div id="vue8">
	<p>8,vue事件处理器</p>
	<button @click="greet('Hello!',event)">Greet!</button>
	<!-- prevent阻止默认事件 -->
	<p>*.prevent</p>
	<form id="vue8form" @submit.prevent="onSubmit">
		name:<input type="text">
		<input type="submit" value="submit">
	</form>
	<a href="https://www.baidu.com" target="_blank" rel="external nofollow"  @click.prevent>点我没用</a><br>
	<!-- once次数限制为1次 -->
	<p>*.once</p>
	<button @click.once="hitOnce">我只能点一次</button>
	<!-- capture捕获 -->
	<p>*.capture</p>
	<div>
		<div id="a" @click="hello1">
			<button @click="hello2">A</button>
		</div>
		<div id="b" @click.capture="hello1">
			<button @click="hello2">B</button>
		</div>
	</div>
	<!-- self仅响应自身的事件 -->
	<p>*.self</p>
	<div @click="hello1">
		第一层
		<div @click.self="hello2">
			第二层
			<div @click="hello3">
				第三层
				<div @click="hello4">
					第四层
				</div>
			</div>
		</div>
	</div>
	<!-- stop阻止 -->
	<p>*.stop</p>
	<div @click="hello1">
		<label @click.stop="hello2">stop冒泡</label>
	</div>

	<!-- 按键事件 -->
	<p>*keyup事件</p>
	<p>
		<input @keyup.delete.prevent="prevDel" v-model="key_del">
	</p>
</div>
<script>
	var vue8 = new Vue({
		el:'#vue8',
		data:{
		    key_del:'aaa'
		},
		methods:{
		    greet:function (message, event) {
				alert(message);
				if(event)
				    alert(event.target.tagName);
            },
			onSubmit:function(){
		        alert('不提交!');
		        console.log("AAA");
		        return false;
			},
			hitOnce:function(){
			    alert("我只弹一次!");
			},
			hello1:function () {
				console.log(1);
            },
            hello2:function () {
                console.log(2);
            },
            hello3:function () {
                console.log(3);
            },
            hello4:function () {
                console.log(4);
            },
            prevDel:function (event) {
				alert(event.key+event.keyCode);
            }
		}
	})
</script>

<!-- 9,vue表单 -->
<div id="vue9">
	<p>9,vue表单</p>
	<form id="vue9form" @submit.prevent="onSubmit">
		name:<input type="text" v-model.trim="name" placeholder="过滤前后空格"><br>
		birthday:<input type="date" v-model.lazy="birthday">&nbsp;age:<input type="text" v-model.number="age" readonly><br>
		sex:<input type="radio" v-model="sex" value="male">male&nbsp;<input type="radio" v-model="sex" value="female">female<br>
		hobbies:<input type="checkbox" v-model="hobbies" value="swimming">swimming&nbsp;
		<input type="checkbox" v-model="hobbies" value="box">box&nbsp;
		<input type="checkbox" v-model="hobbies" value="reading">reading&nbsp;
		<input type="checkbox" v-model="hobbies" value="gaming">gaming<br>
		website:<select v-model="website">
		<option value="">choose a website</option>
		<option value="google">google</option>
		<option value="youtube">youtube</option>
		<option value="xy">xy</option>
	</select><br>
		<input type="submit" value="submit">
	</form>
	<p v-show="show">{{allmessage}}<span v-if="show">隐藏<input type="checkbox" @click="notDisplay"></span></p>
</div>
<script>
	new Vue({
		el:'#vue9',
		data:{
		    name:'',
			birthday:'2001-01-07',
			sex:'male',
			hobbies:[],
			website:'',
			show:false
		},
		computed:{
		    age:function () {
				var mydate = new Date();
				var bird = new Date(this.birthday);
				return mydate.getYear() - bird.getYear();
            },
            allmessage:function () {
                var hobbiesStr = '';
                for(var i = 0; i < this.hobbies.length; i++){
                    hobbiesStr += this.hobbies[i]+",";
                }
                hobbiesStr = hobbiesStr.substring(0,hobbiesStr.length - 1);
                return "name:"+this.name+" birthday:"+this.birthday+
                    " age:"+this.age+" sex:"+this.sex+" hobbies:"+
                    hobbiesStr+" website:"+this.website
            }
		},
		methods:{
		    onSubmit:function () {
				this.show = true;
            },
			notDisplay:function () {
				this.show = false;
            }
		}
	})
</script>

<!-- 10,vue组件 -->
<div id="vue10">
	<p>10,vue组件</p>
	<p>*父组件直接影响子组件内容</p>
	<div>
		<input v-model="parentMsg"><br>
		<child v-bind:message="parentMsg"></child>
	</div>
	<div>
		<ul>
			<todo-item v-for="item in items" v-bind:todo="item"></todo-item>
		</ul>
	</div>
	<p>*子组件借助自定义事件影响父组件内容</p>
	<div>
		<button-counter @increment="incrementTotal"></button-counter>
		 +
		<button-counter @increment="incrementTotal"></button-counter>
		 =
		{{total}}
	</div>
	<p>*Prop验证</p>
	<div>
		<validator-test :onenumber="oneNumber"></validator-test>
	</div>
</div>
<script>
	/*
	父组件可以直接影响子组件的内容,子组件想要影响父组件的内容,需要自定义事件的配合。
	 */
	Vue.component('child',{
        props:['message'],
        template:'<span>{{ message }}</span>'
	});
	Vue.component('todo-item',{
	    props:['todo'],
		template:'<li @click="hello">{{todo.text}}</li>',
		methods:{
	        hello:function(event){
	            alert("Hello! "+event.target.innerText);
			}
		}
	});
	Vue.component('button-counter',{
        /*
        data是一个函数,而不是一个对象的原因:
        每个实例可以维护一份被返回对象的独立的拷贝,
        如果 data 是一个对象则会影响到其他实例
         */
	    data: function(){
	        return {
	            counter:0
			}
		},
		template:'<button @click="incrementHandler">{{counter}}</button>',
		methods:{
	        incrementHandler:function(){
	            this.counter ++;
	            this.$emit('increment');//每当一个按钮自增一次,就触发一次自定义事件
			}
		}
	});
	Vue.component('validator-test',{
	    props:{
	        onenumber:Number
		},
		template:'<p>{{onenumber}}</p>'
	});
	new Vue({
		el:'#vue10',
		data:{
		    parentMsg:'父组件内容',
			items:[
				{text:'刘德华'},
				{text:'古天乐'},
				{text:'吴镇宇'}
			],
			total:0,
			oneNumber:'a'//传入数字才不会有警告。使用vue.min.js控制台不输出对应错误。使用vue.js则会输出对应错误
		},
		methods:{
		    incrementTotal:function(){
		        this.total += 1;
			}
		}
	});
</script>

<!-- 11,vue自定义指令 -->
<div id="vue11">
	<p>11,vue自定义指令</p>
	<p>*页面载入时,自动获取焦点</p>
	<input v-focus>
	<p>*钩子函数参数</p>
	<div v-dirprop:hello.a.b="message"></div><br>
	<div v-dirprop2="{color:'green',text:'vue学习'}"></div>
</div>
<script>
	//定义在外面为全局指令,定义在某个实例中则为局部指令
	/*Vue.directive('focus',{
		inserted:function(el){
		    el.focus();
		}
	});*/
	new Vue({
		el:'#vue11',
		data:{
		    message:'vue学习'
		},
		directives:{
		    focus:{
		        inserted:function(el){
		            el.focus();
				}
			},
			dirprop:{
		        inserted:function(el,binding,vnode){
					var s = JSON.stringify;
					el.innerHTML =
							'name: '+s(binding.name)+'<br>'+
							'value: '+s(binding.value)+'<br>'+
							'expression: '+s(binding.expression)+'<br>'+
							'argument: '+s(binding.arg)+'<br>'+
							'modifiers: '+s(binding.modifiers)+'<br>'+
							'vnode keys: '+Object.keys(vnode).join(',');
				}
			},
            dirprop2:{
		        inserted:function(el,binding){
		            el.innerHTML = binding.value.text;
		            el.style.background = binding.value.color;
				}
			}
		}
	});
</script>

<!-- 12,vue路由 -->
<div id="vue12">
	<p>12,vue路由</p>
	<p>*简单路由</p>
	<!-- 路径精确匹配时激活 -->
	<router-link to="/a" exact-active-class="_active_red">a</router-link>
	<!-- 路径匹配时激活 -->
	<router-link to="/a/2" active-class="_active_pink">a2</router-link>
	<!-- 默认渲染成<a>,渲染成对应tag -->
	<router-link to="/b" tag="button">b</router-link>
	<!-- 对应鼠标事件激活 -->
	<router-link to="/c" event="mouseover">c</router-link>
	<!-- 在当前 (相对) 路径前添加基路径 -->
	<router-link to="/d" append>d</router-link>
	<!-- 点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录 -->
	<router-link to="/e" replace>e</router-link>

	<router-view></router-view>
</div>
<script>
	const a = {template:'<div>a</div>'};
	const a2 = {template:'<div>a2</div>'}
    const b = {template:'<div>b</div>'};
    const c = {template:'<div>c</div>'};
    const d = {template:'<div>d</div>'};
    const e = {template:'<div>e</div>'};

	const routes = [
		{path:'/a', component:a},
		{path:'/a/2', component:a2},
		{path:'/b', component:b},
        {path:'/c', component:c},
        {path:'/d', component:d},
        {path:'/e', component:e}
	];

	const router = new VueRouter({
		routes
	});
	new Vue({
		router
	}).$mount('#vue12');
</script>
<style>
	._active_red{
		background-color: red;
	}

	._active_pink{
		background-color:pink;
	}
</style>

<!-- 13,vue过渡 & 动画 -->
<div id="vue13">
	<p>13,vue过渡 & 动画</p>
	<p>需要对应功能时,再去找。。。</p>
	<button @click="show = !show">点我!小坏蛋</button>
	<transition name="fade">
		<p :style="style1" v-show="show">小坏蛋</p>
	</transition>
</div>
<script>
	new Vue({
		el:'#vue13',
		data:{
		    show:true,
			style1:{
		        fontSize:'30px',
				color:'red'
			}
		}
	})
</script>
<style>
	/* 可以设置不同的进入和离开动画 */
	/* 设置持续时间和动画函数 */
	.fade-enter-active, .fade-leave-active {
		transition: opacity 2s
	}
	.fade-enter, .fade-leave-to /* .fade-leave-active, 2.1.8 版本以下 */ {
		opacity: 0
	}
</style>

<!-- 14,vue混入 -->
<div id="vue14">
	<p>14,vue混入</p>
	<p>*简单混入</p>
	<div id="vue14_1"></div>
	<p>*选项合并</p>
	<div id="vue14_2"></div>
	<div id="vue14_3"><br></div>
	<p>*全局混入</p>
	<div id="vue14_4"></div>
</div>
<script>
	var myMixin = {
	    created:function(){
	        this.startmixin();
		},
		methods:{
	        startmixin:function(){
	            document.getElementById('vue14_1').innerHTML = '混入实例';
			}
		}
	};
	new Vue({
		el:'#vue14_1',
		mixins:[myMixin]
	});

	var myMixin2 = {
	    created:function(){
	        var txt = document.createTextNode('混入调用 ');
	        document.getElementById('vue14_2').appendChild(txt);
		}
	};
	new Vue({
		el:'#vue14_2',
		mixins:[myMixin2],
			created:function(){
                var txt = document.createTextNode('组件调用');
		    	document.getElementById('vue14_2').appendChild(txt);
			}
	});

	var myMixin3 = {
	    methods:{
	        helloworld:function(){
	            var txt = document.createTextNode('hello world! ');
	            document.getElementById('vue14_3').appendChild(txt);
			},
			samemethod:function(){
                var txt = document.createTextNode('samemethod of mixin ');
                document.getElementById('vue14_3').appendChild(txt);
			}
		}
	};
	var vue14_3 = new Vue({
		el:'#vue14_3',
		mixins:[myMixin3],
		methods:{
		    start:function(){
                var txt = document.createTextNode('start mixin test! ');
                document.getElementById('vue14_3').appendChild(txt);
			},
			samemethod:function(){
                var txt = document.createTextNode('samemethod of object ');
                document.getElementById('vue14_3').appendChild(txt);
			}
		}
	});
	vue14_3.start();
	vue14_3.helloworld();
	vue14_3.samemethod();

	Vue.mixin({
		created:function(){
		    var txt = this.sayHello;
		    if(txt){
                document.getElementById('vue14_4').innerText = txt;
            }
		}
	});
	new Vue({
		el:'#vue14_4',
		data:{
		    sayHello:'Hello!'
		}
	});
</script>

<!-- 15,vue Ajax -->
<div id="vue15">
	<p>15,vue Ajax</p>
	<p>*Get请求</p>
	<div id="vue15_1">
		<input type="button" @click="get()" value="点我获取Get">
	</div>
	<p>*Post请求</p>
	<div id="vue15_2">
		<input type="button" @click="post()" value="点我获取Post">
	</div>
</div>
<script>
	//.then('成功回调函数','失败回调函数')
	new Vue({
		el:'#vue15_1',
		methods:{
		    get:function(){
		        //get方式请求数据
		        this.$http.get('http://www.runoob.com/try/ajax/ajax_info.txt').then(function(res){
		            document.getElementById('vue15_1').innerHTML = res.body;
				},function(){
		            console.log('get请求数据失败');
				});
			}
		}
	});
	new Vue({
		el:'#vue15_2',
		methods:{
		    post:function(){
		        //post方式请求数据
		        this.$http.post('http://www.runoob.com/try/ajax/demo_test_post.php',
					{name:'google',url:'https://www.google.com'}, {emulateJSON:true}).then(
					    function(res){
							document.getElementById('vue15_2').innerHTML = res.body;
						},function(){
							console.log('post请求数据失败');
						});
			}
		}
	});
	/*
	使用get方式传递参数到后台方法,前提是访问的后台方法没有限制请求方式。
	 */
	new Vue({
		methods:{
		    getData:function(){
		        this.$http.get('url', {params:{param1:"value1",param2:"value2"}}).then(function(res){
					    //success
				}, function(){
					    //fail
				});
			}
		}
	});
</script>

<!-- 16,vue响应接口 -->
<div id="vue16">
	<p>16,vue响应接口</p>
	<p>*回顾$watch监听</p>
	<!-- $watch监听必须添加在实例外才能正确响应 -->
	<div id="vue16_1">
		<p>{{counter}}</p>
		<button @click="add">点我+1,然后自增20</button>
	</div>
	<p>*Vue.set</p>
	<div id="vue16_2">
		<p @click="setProp()">{{counter2}}</p>
		<button @click="counter2++">这个计数器纯粹占位置的,看控制台就行</button>
	</div>
	<p>*Vue.delete</p>
	<div id="vue16_3">
		<p @click="deleteProp()">{{counter3}}</p>
		<button @click="counter3++">因为空荡荡的,总感觉不安全</button>
	</div>
</div>
<script>
	var vue16_1 = new Vue({
		el:'#vue16_1',
		data:{
		    counter:1
		},
		methods:{
		    add:function(){
		        this.counter++;
		        setTimeout(//设置计时器,每点击按钮一次,2秒后自增20
		            function(){
		                vue16_1.counter += 20;
					}, 2000
				);
			}
		}
	});
	//监听counter属性值变化并反馈
    vue16_1.$watch('counter',function(newValue, oldValue){
        alert('计数器值变化:从'+oldValue+'变成'+newValue);
	});

    var myProducts = {id:1,name:"Tom",price:300};
    var vue16_2 = new Vue({
		el:'#vue16_2',
		data:{
		    counter2:2,
			products:myProducts
		},
		methods:{
		    setProp:function(){
		        Vue.set(myProducts, "anewprop", "123木头人");
		        console.log(vue16_2);
			}
		}
	});
    console.log(vue16_2);
    //使用此方式添加的属性没有get/set方法
    vue16_2.products.mypropA = 1;
	//使用Vue.set方法添加的属性才有
	Vue.set(myProducts, 'mypropB', 2);
	//Vue 不允许在已经创建的实例上动态添加新的根级响应式属性。
	//用此方式添加的属性,没有get/set方法,获取为undefined
    vue16_2.$data.myPropA = "a";
    //此方式相当于定义了一个私有的根属性,可以正常的获取与赋值
	vue16_2.myPropB = "b";

    var myProducts2 = {id:2,name:"Jerry",price:233};
	var vue16_3 = new Vue({
		el:'#vue16_3',
		data:{
		    counter3:3,
			products:myProducts2,
			testProp:"aaa"
		},
		methods:{
		    deleteProp:function(){
		        //允许删除动态添加的属性
		        Vue.delete(myProducts2, "price");
		        //不允许删除实例的根属性的静态属性
//		        Vue.delete(vue16_3.$data, "testProp");
				//不允许删除实例的根属性的静态方法
//		        Vue.delete(vue16_3.$methods, "testMethod");
				//不允许删除实例的根属性
//				Vue.delete(vue16_3, "$computed");
		        console.log(vue16_3);
			},
			testMethod:function(){}
		},
		computed:{
		    getProp:function(){}
		}
	});
	console.log(vue16_3);

</script>
</body>
</html>
           

继续阅读