Vue 听起来就高大上, 简单的几行代码, 实现了意想不到的功能, 一下子把静态的网页变成了动态, 把JavaScript和XML标签无缝对接到了一起.
其实神秘的操作背后, 是大量使用的观察者的模式. 在XML语言中, 安插了一个个小间谍, 实时把消息通知给了自己的朋友.
下面的24个小程序, 可以直接在网页中浏览. 学习别人的代码, 反复实践, 才是快速成长的王道.
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>玩转Vue的24个小程序 -- 基础篇</title> 6 <script src="vue.min.js"></script> 7 </head> 8 9 <style> 10 .class1{ 11 background: #444; 12 color: #eee; 13 } 14 </style> 15 16 <style> 17 .active { 18 width: 100px; 19 height: 100px; 20 background: green; 21 } 22 .text-danger { 23 background: red; 24 } 25 </style> 26 27 <body> 28 29 <!-- input 中, 绑定 Lazy, number, Trim 属性 --> 30 <div id="app24"> 31 <input v-model.lazy="msg" placeholder="请输入..."> 32 <p>输入的消息是:{{msg}}</p> 33 <input v-model.number="age" type="number"> 34 <p>输入的年龄是:{{age}}</p> 35 <input v-model.trim="msg2" placeholder="请输入..."> 36 <p>输入的消息是:{{msg2}}</p> 37 </div> 38 39 <script> 40 new Vue ({ 41 el: '#app24', 42 data:{ 43 msg: '', 44 age: 30, 45 msg2: '' 46 } 47 }) 48 49 document.write('==========24==============') 50 </script> 51 52 <!-- select 的使用方法 --> 53 <div id="app23"> 54 <select v-model="selected" name="fruit"> 55 <option value="">选择一个网站</option> 56 <option value="www.runoob.com">Runoob</option> 57 <option value="www.google.com">Google</option> 58 </select> 59 60 <div id="output"> 61 选择的网站是: {{selected}} 62 </div> 63 </div> 64 65 <script> 66 new Vue({ 67 el: '#app23', 68 data: { 69 selected: '' 70 } 71 }) 72 73 document.write('==========23==============') 74 </script> 75 76 <!-- checkbox 单复选框和多复选框 --> 77 <div id="app22"> 78 <p>单个复选框:</p> 79 <input type="checkbox" id="checkbox" v-model="checked"> 80 <label for="checkbox">{{ checked }}</label> 81 82 <p>多个复选框:</p> 83 <input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames"> 84 <label for="runoob">Runoob</label> 85 <input type="checkbox" id="google" value="Google" v-model="checkedNames"> 86 <label for="google">Google</label> 87 <input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames"> 88 <label for="taobao">taobao</label> 89 <br> 90 <span>选择的值为: {{ checkedNames }}</span> 91 </div> 92 93 <script> 94 new Vue({ 95 el: '#app22', 96 data: { 97 checked : false, 98 checkedNames: [] 99 } 100 }) 101 102 document.write('==========22==============') 103 </script> 104 105 <!-- input , textarea --> 106 <div id="app21"> 107 <p>input 元素:</p> 108 109 <input v-model="message" placeholder="编辑我……"> 110 <p>消息是: {{ message }}</p> 111 <p>textarea 元素:</p> 112 113 <textarea rows = '5' cols = '30' v-model="message2" placeholder="多行文本输入……"></textarea> 114 <p style="white-space: pre">输入的文本是:{{ message2 }}</p> 115 </div> 116 117 <script> 118 new Vue({ 119 el: '#app21', 120 data: { 121 message: 'Runoob', 122 message2: '菜鸟教程 http://www.runoob.com' 123 } 124 }) 125 document.write('==========21==============') 126 </script> 127 128 129 <!-- css属性更改3 --> 130 <div id="app20"> 131 <div v-bind:class="classObject"></div> 132 </div> 133 134 <script> 135 new Vue({ 136 el: '#app20', 137 data: { 138 isActive: true, 139 error: { 140 value: false, 141 type: 'fatal' 142 } 143 }, 144 computed: { 145 classObject: function () { 146 return { 147 base: true, 148 'active': this.isActive && !this.error.value, 149 'text-danger': this.error.value && this.error.type === 'fatal', 150 } 151 } 152 } 153 }) 154 document.write('==========20==============') 155 </script> 156 157 <!-- css属性更改2 --> 158 <div id="app19"> 159 <div v-bind:class="classObject"></div> 160 </div> 161 162 <script> 163 new Vue({ 164 el: '#app19', 165 data: { 166 classObject: { 167 'active': true, 168 'text-danger': true 169 } 170 } 171 }) 172 document.write('==========19==============') 173 </script> 174 175 <!-- css属性更改1 --> 176 <div id="app18"> 177 <div class="static" 178 v-bind:class="{ 'active': isActive, 'text-danger': hasError }"> 179 </div> 180 </div> 181 182 <script> 183 vm = new Vue({ 184 el: '#app18', 185 data: { 186 isActive: true, 187 hasError: true 188 } 189 }) 190 191 document.write('==========18==============') 192 </script> 193 194 195 <!-v-model 绑定, 相当于 <input :value="kilometers" @input="kilometers = $event.target.value">--> 196 <div id = "app17"> 197 千米 : <input type = "text" v-model = "kilometers"> 198 米 : <input type = "text" v-model = "meters"> 199 </div> 200 <p id="info"></p> 201 <script type = "text/javascript"> 202 var vm = new Vue({ 203 el: '#app17', 204 data: { 205 kilometers : 0, 206 meters:0 207 }, 208 methods: { 209 }, 210 computed :{ 211 }, 212 watch : { 213 kilometers:function(val) { 214 this.kilometers = val; 215 this.meters = this.kilometers * 1000 216 }, 217 meters : function (val) { 218 this.kilometers = val/ 1000; 219 this.meters = val; 220 } 221 } 222 }); 223 // $watch 是一个实例方法 224 vm.$watch('kilometers', function (newValue, oldValue) { 225 // 这个回调将在 vm.kilometers 改变后调用 226 document.getElementById ("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue; 227 }) 228 229 document.write('==========17==============') 230 </script> 231 232 <!-- @click 事件响应, 计数器 --> 233 <div id = "app16"> 234 <p style = "font-size:25px;">计数器: {{ counter }}</p> 235 <button @click = "counter++" style = "font-size:25px;">点我</button> 236 </div> 237 <script type = "text/javascript"> 238 var vm = new Vue({ 239 el: '#app16', 240 data: { 241 counter: 1 242 } 243 }); 244 vm.$watch('counter', function(nval, oval) { 245 console.log('计数器值的变化 :' + oval + ' 变为 ' + nval + '!'); 246 }); 247 248 document.write('==========16==============') 249 </script> 250 251 <!-- @click 事件响应, 超链接跳转 --> 252 <div id="app15"> 253 <p @click = "todo" >name : {{name}}</p> 254 <p>url : <a :href = "url" > {{url}}</a> </p> 255 <p>site : {{site}}</p> 256 </div> 257 258 <script> 259 var vm = new Vue({ 260 el: '#app15', 261 data: { 262 name: 'Google', 263 url: 'http://www.google.com' 264 }, 265 methods:{ 266 todo:function(){ 267 window.open(this.url) 268 } 269 }, 270 computed: { 271 site: { 272 // getter 273 get: function () { 274 return this.name + ' ' + this.url 275 }, 276 // setter 277 set: function (newValue) { 278 var names = newValue.split(' ') 279 this.name = names[0] 280 this.url = names[names.length - 1] 281 } 282 } 283 } 284 }) 285 286 // 调用 setter, vm.name 和 vm.url 也会被对应更新 287 vm.site = 'Runoob http://www.runoob.com'; 288 289 document.write('==========15==============') 290 </script> 291 292 <!-- computed methods --> 293 <!--使用 computed属性 或 methods computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。 :--> 294 <div id="app14"> 295 <p>原始字符串: {{ message }}</p> 296 <p>计算后反转字符串: {{ reversedMessage }}</p> 297 <p>使用方法后反转字符串: {{ reversedMessage2() }}</p> 298 </div> 299 300 <script> 301 var vm = new Vue({ 302 el: '#app14', 303 data: { 304 message: 'Runoob!' 305 }, 306 computed: { 307 // 计算属性的 getter 308 reversedMessage: function () { 309 // `this` 指向 vm 实例 310 return this.message.split('').reverse().join('') 311 } 312 }, 313 methods: { 314 reversedMessage2: function () { 315 return this.message.split('').reverse().join('') 316 } 317 } 318 }) 319 document.write('==========14==============') 320 </script> 321 322 <!--使用 v-for 迭代器 :--> 323 <div id="app13"> 324 <ul> 325 <li v-for="value in object"> 326 {{ value }} 327 </li> 328 </ul> 329 </div> 330 331 <script> 332 new Vue({ 333 el: '#app13', 334 data: { 335 object: { 336 name: '菜鸟教程', 337 url: 'http://www.runoob.com', 338 slogan: '学的不仅是技术,更是梦想!' 339 } 340 } 341 }) 342 document.write('==========13=============') 343 </script> 344 345 <!--使用 v-for :--> 346 <div id="app12"> 347 <ul> 348 <template v-for="site in sites"> 349 <li>{{ site.name }}</li> 350 </template> 351 </ul> 352 </div> 353 354 <script> 355 new Vue({ 356 el: '#app12', 357 data: { 358 sites: [ 359 { name: 'Runoob' }, 360 { name: 'Google' }, 361 { name: 'Taobao' } 362 ] 363 } 364 }) 365 document.write('==========12==============') 366 </script> 367 368 <!-- 完整语法 --> 369 <a v-bind:href="url"></a> 370 <!-- 缩写 --> 371 <a :href="url"></a> 372 373 <!-- 完整语法 --> 374 <a v-on:click="doSomething"></a> 375 <!-- 缩写 --> 376 <a @click="doSomething"></a> 377 378 <div id="app11"> 379 <pre><a :href="url">{{ message }}</a></pre> 380 <button @click="reverseMessage">反转字符串</button> 381 </div> 382 383 <script> 384 new Vue({ 385 el: '#app11', 386 data: { 387 url: 'http://www.runoob.com', 388 message: 'Runoob' 389 }, 390 methods: { 391 reverseMessage: function () { 392 this.message = this.message.split('').reverse().join('') 393 } 394 } 395 }) 396 document.write('==========11==============') 397 </script> 398 399 <!-- filters --> 400 <div id="app10"> 401 {{ message | capitalize }} 402 </div> 403 404 <script> 405 new Vue({ 406 el: '#app10', 407 data: { 408 message: 'runoob' 409 }, 410 filters: { 411 capitalize: function (value) { 412 if (!value) return '' 413 value = value.toString() 414 return value.charAt(0).toUpperCase() + value.slice(1,value.length-1) + value.slice(value.length-1).toUpperCase() 415 } 416 } 417 }) 418 419 document.write('==========10==============') 420 </script> 421 422 <!-- v-on:click --> 423 <div id="app9"> 424 <p>{{ message }}</p> 425 <button v-on:click="reverseMessage">反转字符串</button> 426 </div> 427 428 <script> 429 new Vue({ 430 el: '#app9', 431 data: { 432 message: 'Runoob!' 433 }, 434 methods: { 435 reverseMessage: function () { 436 this.message = this.message.split('').reverse().join('') 437 } 438 } 439 }) 440 document.write('==========9==============') 441 </script> 442 443 444 <!-- v-model 内容绑定 --> 445 <div id="app8"> 446 <p>{{ message }}</p> 447 <input v-model="message"> 448 </div> 449 450 <script> 451 new Vue({ 452 el: '#app8', 453 data: { 454 message: 'Runoob!' 455 } 456 }) 457 458 document.write('==========8==============') 459 </script> 460 461 <!-- v-bind 链接绑定 --> 462 <div id="app7"> 463 <pre><a v-bind:href="url">菜鸟教程</a></pre> 464 </div> 465 466 <script> 467 new Vue({ 468 el: '#app7', 469 data: { 470 url: 'http://www.runoob.com' 471 } 472 }) 473 document.write('==========7==============') 474 </script> 475 476 <!--指令是带有 v-if v-else 前缀的特殊属性。--> 477 <div id="app6"> 478 <p v-if="seen">现在你看到我了</p> 479 <p v-if="disp">我看不到你了</p> 480 </div> 481 482 <script> 483 new Vue({ 484 el: '#app6', 485 data: { 486 seen: false, 487 disp: true 488 } 489 }) 490 document.write('===========6=============') 491 </script> 492 493 494 <!--Vue.js 都提供了完全的 JavaScript 表达式支持。--> 495 <div id="app5"> 496 {{5+5}}<br> 497 {{ ok ? 'YES' : 'NO' }}<br> 498 {{ message.split('').reverse().join(' ') }} 499 <div v-bind:id="'list-' + id">菜鸟教程</div> 500 </div> 501 502 <script> 503 new Vue({ 504 el: '#app5', 505 data: { 506 ok: true, 507 message: 'RUNOOB', 508 id : 1 509 } 510 }) 511 document.write('===========5=============') 512 </script> 513 514 <!-- v-bind 绑定 --> 515 <div id="app4"> 516 <label for="r1">修改颜色</label> 517 <input type="checkbox" v-model="use1" id="r1"> 518 <input type="checkbox" v-model="use2" id="r2"> 519 <br><br> 520 <div v-bind:class="{'class1': use2}"> 521 v-bind:class 指令 522 </div> 523 </div> 524 525 <script> 526 new Vue({ 527 el: '#app4', 528 data:{ 529 use1: true, 530 use2: false 531 } 532 }); 533 document.write('===========4=============') 534 </script> 535 536 537 <!--使用 v-html 指令用于输出 html 代码:--> 538 <div id="app3"> 539 <div v-html="message"></div> 540 </div> 541 <script> 542 new Vue({ 543 el: '#app3', 544 data: { 545 message: '<h5>RUNOOB</h5>' 546 } 547 }) 548 549 document.write('==========3==============') 550 </script> 551 552 <!-- JSON结构的数据输入 --> 553 <div id="app2"> 554 <h3>site : {{site}}</3> 555 <h4>url : {{url}}</h4> 556 <p>{{details()}}</p> 557 <p>Alexa : {{alexa}}</p> 558 </div> 559 560 <script> 561 var data = { site: "RUNOOB", url: "www.runoob.com", alexa: 10000} 562 var vm = new Vue({ 563 el: '#app2', 564 data: data, 565 methods: { 566 details: function() { 567 return this.site + " - 学的不仅是技术,更是梦想!"; 568 } 569 } 570 }) 571 document.write('==========2==============') 572 </script> 573 574 <div id="app"> 575 <p>{{ message }}</p> 576 </div> 577 578 <!-- 第一个小程序 --> 579 <script> 580 new Vue({ 581 el: '#app', 582 data: { 583 message: '<h1>RUNOOB</h1>' 584 } 585 }) 586 //<!--传递Data参数:--> 587 588 document.write('==========1==============') 589 </script> 590 591 </body> 592 </html>