主要学习资料为菜鸟教程的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"> age:<input type="text" v-model.number="age" readonly><br>
sex:<input type="radio" v-model="sex" value="male">male <input type="radio" v-model="sex" value="female">female<br>
hobbies:<input type="checkbox" v-model="hobbies" value="swimming">swimming
<input type="checkbox" v-model="hobbies" value="box">box
<input type="checkbox" v-model="hobbies" value="reading">reading
<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>