由于本vue教程的参考视频太旧,不再更新,请移步新版尚硅谷Vue技术全家桶(1)

介绍

vue.js 是什么

vue.js是个开发前端页面的渐进式框架。
至于什么是渐进式,引用渐进式的理解这篇博文的开头:Vue渐进式-先使用Vue的核心库,再根据你的需要的功能再去逐渐增加相应的插件。
官方也说:Vue 被设计为可以自底向上逐层应用。

起步引入

1.CDN引入(了解)

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>

安装教程给出了更多安装 Vue 的方式。请注意我们不推荐新手直接使用 vue-cli,尤其是在你还不熟悉基于 Node.js 的构建工具时。

2. npm安装(常用)

npm install vue

声明式渲染

初次体验

目录结构:

vue01.html:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><!-- div放在script标签前面才能读到message --><div id="app">{{message}}<ul><!-- v-for遍历 --><li v-for="item in movies">{{item}}</li></ul>当前计数:{{counter}}<button v-on:click="counter++">+</button><!--函数式实现counter加法--><button v-on:click="sub">-</button><!--sub函数实现counter减法--></div><!-- 引入 --><script src="./node_modules/vue/dist/vue.js"></script><script>const app = new Vue({el: "#app",// 挂载id=app的元素data: {message: "hello vue",movies: ["one", "two", "three"],counter: 0},methods: {sub: function() {//减法函数subthis.counter--;//注意使用this}}})</script>
</body></html>

message会显示为data里面的message数据hello vue,并且会随着data改变而改变。
初次体验发现js代码要放到页面元素下面,或者直接放到head里,目前不知道什么原因。
显示结果:

MVVM思想

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。

MVVM与MVC的区别有:1、mvvm各部分的通信是双向的,而mvc各部分通信是单向的;2、mvvm是真正将页面与数据逻辑分离放到js里去实现,而mvc里面未分离。



灵魂发问:方法和函数有什么区别?
一般通用的调用的叫函数,而类实例中的一般叫方法。

生命周期(理解)


生命周期函数,和methods,data,el等等是并列的。
Vue经典生命周期图:

插值操作(内容绑定)(掌握)

包括Mustache语法(双大括号)、v-once、v-html、v-text、v-pre、v-cloak

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app"><!-- hello vue! +中文测试 --><h2>{{message}}</h2><!-- hello vue! +中文测试,coder --><h2>{{message}},coder</h2><!-- kobe bryant --><h2>{{firstName+" "+lastName}}</h2><!-- kobe bryant --><h2>{{firstName}} {{lastName}}</h2><!-- 200 --><h2>{{counter*2}}</h2><!-- 200,不能更改 --><h2 v-once>{{counter*2}}</h2><!-- baidu --><h2 v-html="url"></h2><!-- text content --><h2 v-text="text"></h2><!-- text content --><h2 v-text="text">被v-text覆盖的内容</h2><!-- {{pretest}} --><h2 v-pre>{{pretest}}</h2><!-- cloakTest-context --><h2 v-cloak>{{cloakTest}}</h2></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {//Mustache语法(胡须、双大括号语法)说明://可以对数据处理,包括数字的简单运算,字符串的连接message: 'hello vue! +中文测试',firstName: 'kobe',lastName: 'bryant',counter: 100,//v-html直接插入代码//url说明://1.外面单引号,里面双引号//2.地址引用的时候加‘http://’不然找的是/test-vue/www.baidu.com,可以ctrl左键看能不能过去url: '<a href="http://www.baidu.com">baidu</a>',//v-text说明//1.虽然能达到双大括号一样的效果,但不够灵活,不能像双大括号第2个示例一样在后面加东西、处理//2.如果标签内有东西的话会覆盖标签内容,见v-text例子2text: 'text content',//v-pre说明//原封不动的显示元素内容,而不是把数据映射替换上去pretest: 'pretest-context',//v-cloak说明//页面渲染是从上往下执行的,如果js执行的慢或者出错没执行,会让用户长久看到‘{{cloakTest}}’,因此需要v-cloak,不加载数据就不显示'{{cloakTest}}'cloakTest: 'cloakTest-context'},methods: {}})</script>
</body></html>

v-once:一次性插值

V-bind:属性绑定操作(掌握)

介绍

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.active {color: red;}</style></head><body><div id="app"><!-- 错误的做法,属性绑定不能用mustache语法 --><!-- <img src="{{imgURL}}" > --><!-- 正确的做法:使用v-bind绑定属性 --><img v-bind:src="imgURL"><a v-bind:href="aHref">baidu</a><!-- 语法糖,简写 --><a :href="aHref">baidu</a><!-- class属性的绑定 --><h2 :class="styleName">{{message}}</h2><!-- 开发中经常用的,是绑定一个对象,通过true和false控制k1、k2等的绑定于否 --><!-- <h2 v-bind:class="{k1: v1,k2:v2}">{{message}}</h2> --><!-- <h2 v-bind:class="{类名1:true,类名2:false}">{{message}}</h2> --><h2 v-bind:class="{ active: isActive,line :isLine}">{{message}}</h2><button v-on:click="btnclick">变颜色</button><!-- 如果class太长,可以通过方法来引入,方法一般是有()括号的,前面的btnclick是省略了。 --><h2 v-bind:class="getClasses()">{{message}}</h2><!-- 数组绑定,元素加单引号是表示为字符串,不加单引号是表示引用 --><h2 v-bind:class="['num1',num2]">{{message}}</h2><!-- 方法引入数组 --><h2 v-bind:class="getArray()">{{message}}</h2></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {//JD上的一个图片地址imgURL: 'https://img12.360buyimg.com/seckillcms/s140x140_jfs/t1/175314/15/16276/177538/60d2af50Ee7ca5162/1bad140689e2acac.jpg.webp',aHref: 'https://www.baidu.com',message: 'message-context',styleName: 'active',isActive: true,isLine: false,num1: 'aaaaa',num2: 'bbbbb'},methods: {btnclick: function(){this.isActive=!this.isActive},getClasses: function(){return {active: this.isActive,line: this.isLine}},getArray: function(){//[num1,num2]return [this.num1,this.num2]}}})</script>
</body></html>

设置为false的属性其实是渲染的时候没有带上;注意引号区别下渲染出的值:

v-bind绑定style

绑定class有两种方式:

  1. 对象语法
  2. 数组语法

样式为什么要动态?
当进行组件化开发时,样式是要动态绑定的,对象语法用的多。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.title{font-size: 50px;color: red;}</style>
</head><body><div id="app"><!-- 对象形式 --><!-- 省略了v-bind;50px不加引号会当成变量 --><h2 :style="{fontSize:'50px'}">{{message}}</h2><!-- 对象形式 --><h2 :style="{fontSize:fontSize}">{{message}}</h2><!-- 对象抽取成方法形式 --><h2 :style="getStyle()">{{message}}</h2><!-- 数组形式 --><h2 :style="[style1,style2]">{{message}}</h2><h2 :style="[getStyle(),getAnotherStyle()]">{{message}}</h2></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {message: 'message-context',fontSize: '50px',color: 'red',style1:{color:'red'},style2:{fontSize:'50px'}},methods: {getStyle: function(){return {fontSize:this.fontSize}},getAnotherStyle: function(){return {color:this.color}    }}})</script>
</body></html>

计算属性

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app"><!-- 普通形式 --><h2>{{firstName+' '+lastName}}</h2><h2>{{firstName}} {{lastName}}</h2><!-- 函数式,函数式要带括号 --><h2>{{getFullName()}}</h2><!-- 计算式,计算式不需要小括号,其实本质是个函数,是个函数式的语法糖,只是这样不带括号看起来更像个变量而不是方法 --><!-- 需要数据处理以后得到的变量值推荐使用计算式,符合变量的形式而且计算式比函数式多了缓存,只需要计算一次,处处使用 --><h2>{{fullName}}</h2><div>{{totalPrice}}</div><h2>{{fullName02}}</h2></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {firstName: 'firstName',lastName: 'lastName',books: [{id:001,name:'book1',price: 10},{id:002,name:'book2',price: 20},{id:003,name:'book3',price: 30},{id:004,name:'book4',price: 40},]},methods: {getFullName: function () {return this.firstName + ' ' + this.lastName}},// 计算属性// 完整的计算属性是包含get、set两个方法的,正常默认使用的是get方法computed: {fullName: function () {return this.firstName + ' ' + this.lastName},totalPrice: function(){let result=0for(let i=0;i<this.books.length;i++){result+=this.books[i].price}return result},fullName02:{get: function(){return this.firstName + ' ' + this.lastName  },//这里的set不是java中设置值的意思,而是当fullName02改变时会触发set方法。// set方法可以传入改变后的新值,也可以什么都不传set: function(newValue){alert('fullName02 is changed,new:'+newValue)}}}})</script>
</body></html>

修改fullName02值时触发set方法:

插曲:ES6新特性

  1. ES6var和let作用域小知识:
    ES5之前因为if和for都没有作用域的概念,所以在很多时候,必须借助于function的作用域解决应用外面变量的问题(即使用闭包)。
    ES6加入了let,let是有作用域的。
    变量无脑用let基本就够了。
  2. const:
    常量修饰符;
    建议在ES6开发中,优先使用const,除非需要改变某个标识符时才用let;
    声明时必须赋值。
  3. 对象字面量的增强写法

v-on事件监听

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app"><h3>{{counter}}</h3><button v-on:click="counter++">+</button><!-- 函数写法+语法糖 --><button @click="decrement()">-</button><!-- 参数相关 --><!-- 无参时加不加括号无所谓 --><button @click="click1()">button1</button><button @click="click2">button2</button><!-- 无参时参考函数无参情况 --><!-- 123 --><button @click="click3(123)">button3-click3(123)</button><!-- undefined --><button @click="click3()">button3-click3()</button><!-- [object MouseEvent](鼠标事件对象:比如当在浏览器上随便拖拽,就会产生该对象) --><button @click="click3">button3-click3</button><!-- 通过$event可以拿到[object MouseEvent]鼠标事件 --><!-- undefined(字符串不加引号会被当成一个变量,该变量不存在,当然是undefined),[object MouseEvent] --><button @click="click4(abc,$event)">button4-1</button><!-- abc,[object MouseEvent] --><button @click="click4('abc',$event)">button4-2</button><!-- v-on修饰符 --><div @click="divClick"><p>------divClick事件范围内-------</p><!-- 点aaa会触发divClick --><p>aaa</p><!-- 为了防止事件冒泡,使得点击button5不触发divClick,就需要.stop, --><button @click.stop="click5()">button5</button><form action="baidu"><!-- 阻止该元素点击触发时会触发的默认事件(这里默认事件是提交) --><input type="submit" value="提交" @click.prevent="click5"></form><!-- 监听键盘按键弹起,还有keyDown之类的 --><input type="text" @keyup="keyUp"><!-- 自定义组件监听要加.native才监听得到 --><myComponent @click.native="click5">.natice测试</myComponent><!-- 事件只触发一次 --><button @click.once="click5">.once测试</button><p>------divClick事件范围内-------</p></div></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {counter: 0},methods: {decrement() {this.counter--;},click2() {alert('click2')},click3(abc) {alert(abc)},click4(abc, event) {alert(abc)alert(event)},divClick() {alert('divClick')},click5() {alert('click5')},keyUp(){alert('keyUp')}}})</script>
</body></html>

函数碰到无参时的情况,控制台输出undefined:

v-if,v-else-if,v-else

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app"><!-- message-context --><h2 v-if="true">{{message}}</h2><!-- 设为false该元素不渲染 --><h2 v-if="false">{{message}}</h2><!-- data中变量代替 --><h2 v-if="isShow">{{message}}</h2><!-- 不显示时该元素不渲染 --><!-- 即使上面第二个v-is="false",也不渲染,因为v-else受最近的前面的v-if影响 --><h2 v-else>当v-if为false时显示我</h2><div><!-- 复杂判断其实不推荐通过v-if写在页面元素里,推荐使用计算属性 --><h2 v-if="score>=90">优秀</h2><h2 v-else-if="score>=80">良</h2><h2 v-else-if="score>=60">及格</h2><h2 v-else>不及格</h2></div><!-- 通过计算属性改写上面的div --><h2>{{scoreResult}}</h2><!-- v-if实现用户登录切换小案例 --><div><!-- 用户登录形式 --><span v-if="isUseUserName"><!-- for属性会让点击该label后焦点聚焦在id=userName的元素里 --><label for="userName">userName:</label><!-- placeholder属性表示未输入时的框内提示 --><input type="text" id="userName" placeholder="userName" key="userName"><label for="passWord">passWord:</label><input type="password" id="passWord" placeholder="passWord"></span><!-- 邮箱登录形式 --><span v-else><label for="emailName">emailName:</label><input type="text" id="emailName" placeholder="emailName" key="emailName"><label for="passWord">passWord:</label><input type="password" id="passWord" placeholder="passWord"></span><!-- 当点击切换登陆时,会发现input框内的数据没有清除这是因为vue底层在设计时用了复用的思想,它会比较切换前后代码的异同,相同的结构就复用所以切换时其实是用的同一套input元素,只是里面属性改了改,所以当然input框内的数据就没有清除了如果想清除就要告诉vue,input不是同一个,使用key属性标识,key相同的是一套,元素复用、数据互相共享不清除,key不同的就重新建一个元素,当然数据就不保留了 --><button @click="changeLoginMethod()">切换登录类型</button></div></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {message: 'message-context',isShow: false,// score: undefined时结果为不及格score: 70,isUseUserName: true},methods: {changeLoginMethod() {return this.isUseUserName = !this.isUseUserName}},computed: {scoreResult() {let scoreResult = '';if (this.score >= 90) {scoreResult = '优秀'} else if (this.score >= 80) {scoreResult = '良'} else if (this.score >= 60) {scoreResult = '及格'} else {scoreResult = '不及格'}return scoreResult}}})</script>
</body></html>

v-show

对比项 v-if v-show
是否真正渲染: 不在DOM中渲染 在DOM中渲染,只是display属性为none
使用情况: 一次切换的元素 频繁显示隐藏切换的元素

v-for

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app"><!-- 遍历数组 --><!-- 遍历过程中没有使用索引值 --><ul><li v-for="name in names ">{{name}}</li></ul><!-- 遍历时获取索引值 --><!-- 0-one1-two2-three3-four --><ul><li v-for="(name,index) in names ">{{index}}-{{name}}</li></ul><!-- 遍历对象 --><!-- 注意value,key,index的顺序 --><!-- 不一定是value,key,index,这里使用这几个单词是便于理解这个位置上的是什么 --><!-- 0-name-coderhao1-age-252-height-170 --><ul><li v-for="(value,key,index) in info">{{index}}-{{key}}-{{value}}</li></ul><!-- 官方推荐使用v-for时,给对应的元素或组件添加一个:key属性 --><!-- 如果不用key属性,假如在data的数组letters的'c'和'd'中间多加了一个新的'g',则在渲染的时候通过vue的diff分析器就会导致以下渲染情况:c->g,d->c,e->d,f->e,最后+f,类似java数组中间插入新元素导致从插入的位置开始后面的元素都往后挪,这会导致性能问题。而如果设个key则在改变数据后重新渲染时告诉vue复用时通过key设置的标识来对比,这是同一个,它就会复用已有的渲染结果   --><ul><!-- key使用value是个唯一标识,index不是,绑定的一般是个类似数据库中主键一样的东西,保证唯一 --><li v-for="(value,index) in letters " :key="value">{{index}}-{{value}}</li></ul></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {names: ['one', 'two', 'three', 'four'],info: {name: 'coderhao',age: 25,height: 170},letters: ['a','b','c','d','e','f']},methods: {}})</script>
</body></html>

插曲:哪些数组的方法是响应式的

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app"><ul><li v-for="value in letters" >{{value}}</li></ul><button @click="click">vue.set()方法修改元素值</button></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {letters: ['a','b','c','d']},methods: {click(){// 要修改的对象,索引值,修改后的值// Vue.set(vm.object/array, propertyName/index, value);Vue.set(this.letters, 0, 'a_update');}}})</script>
</body></html>


总结:
push/pop/splice/shift/unshift/sort/reverse 响应式
通过索引改变数组中的元素是非响应式的,因为vue内部没有监听这种方式的元素改变。
所以使用vue自带的set方法来改。

案例

1.

题目:

开始时默认让海王为红色,之后点谁谁红,之前的变回黑色。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.redStyle {color: red;}</style>
</head><body><div id="app"><ul><li v-for="(movie,index) in movies" :class="{redStyle: currentIndex===index}" @click="liclick(index)">{{movie}}</li></ul></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {movies: ['海王', '海贼王', '加勒比海盗', '海尔兄弟'],currentIndex: 0},methods: {liclick(index) {this.currentIndex=index}}})</script>
</body></html>

2.


题目:显示上图效果,且购买数量会影响总价,点击移除会移除当前书籍,全部移除会显示“购物车为空”

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app"><div v-if="books.length"><table><thead><tr><th v-for="thead in theads">{{thead}}</th></tr></thead><tbody><tr v-for="(book,index) in books"><!-- 由于有的td不只是遍历出来那么简单,所以这里就手动写,不用v-for --><!-- <td v-for="value in book">{{value}}</td> --><td>{{book.id}}</td><td>{{book.name}}</td><td>{{book.date}}</td><!-- 保留两位小数 --><!-- <td>{{'¥'}}{{book.price.toFixed(2)}}</td> --><!-- 这里使用过滤器来处理price --><td>{{book.price|showPrice}}</td><td><!-- 按钮要知道是哪个书进行加减操作,需要传入index --><button @click="increase(index)">+</button>{{book.count}}<button @click="decrease(index)" :disabled="book.count<=1?true:false">-</button></td><td><button @click="removeBtnClick(index)">移除</button></td></tr></tbody></table><h5>总价格:{{totalCost|showPrice}}</h5></div><h2 v-else>{{'购物车为空'}}</h2></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {theads: ['', '书籍名称', '出版日期', '价格', '购买数量', '操作'],books: [{ id: 1, name: '《算法导论》', date: '2006-9', price: 85.00, count: 1 },{ id: 2, name: '《UNIX编程艺术》', date: '2006-2', price: 59.00, count: 1 },{ id: 3, name: '《编程珠玑》', date: '2008-10', price: 39.00, count: 1 },{ id: 4, name: '《代码大全》', date: '2006-3', price: 128.00, count: 1 }]},methods: {increase(index) {this.books[index].count++},decrease(index) {if(this.books[index].count)this.books[index].count--},removeBtnClick(index){//this.books[index].count=0this.books.splice(index,1)}},computed: {totalCost() {let totalCost=0for(let i=0;i<this.books.length;i++){totalCost+=this.books[i].price*this.books[i].count}return totalCost}},filters: {showPrice(price) {return '¥' + price.toFixed(2)}}})</script>
</body>
</html>

补充说明:

  1. 经过测试发现,在splice移除books的某一条记录时,其他的后面的记录index会自动往前挪,并且也不需要将移除的记录的count置为0,计算结果会正确的剪掉splice移除的记录。
  2. totalCost的不同不同实现方式其实代表了不同的编程范式:
    命令式编程–声明式编程,面向对象编程–面向函数编程(比较)

插曲:js高阶函数与箭头函数初步接触

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app"><h2>{{result}}</h2></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {nums: [10, 20, 111, 222, 333, 40, 50],},methods: {},computed: {// 假设要对nums数组进行处理:找到小于100的数,然后*2,然后相加得结果result() {// 1.// 如果是常规写法,要进行循环遍历;如果使用高阶函数,会简洁的多// let result = 0// for (let index = 0; index < this.nums.length; index++) {//   if (this.nums[index] < 100) {//     result += this.nums[index] * 2//   }// }// return result// 2.// 高阶函数filter,map,reduce// filter进行遍历过滤,map进行遍历处理,reduce进行迭代运算// let result=this.nums.filter(function(n){//   return n<100// }).map(function(n){//   return n*2// }).reduce(function(preValue,n){//   return preValue+n// },0)//迭代初始值(即第一个preValue):0// return result//3.// 高阶函数+箭头函数let result = this.nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n)return result}}})</script>
</body></html>

v-model

实现表单元素和数据的双向绑定

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app"><!-- input元素绑定了data里面的message,所有需要message的地方都会跟着变 --><input type="text" v-model="message1"><h4>{{message1}}</h4><!-- v-model的原理 --><!-- 通过v-bind绑定属性value,实现data改变引起{{message2}}改变; --><!-- 通过v-on绑定事件input,input方法实现{{message2}}改变引起data改变。 --><!-- input没写括号,会默认传入事件。 --><input type="text" :value="message2" @input="input"><!-- 或者使用简便写法,不用input()方法了 --><input type="text" :value="message2" @input="message2=$event.target.value"><h4>{{message2}}</h4><!-- textarea元素也可以 --><textarea v-model="message2">{{message2}}</textarea><br><!-- 结合radio单选框 --><label for="male"><!-- 两个radio的name一样保障是同一个范围内的,单选框会互斥 --><!-- 多个radio的v-model绑定同一个data的话,name可以省略,依然互斥 --><input type="radio" id="male" name="sex" value="男" v-model="sex">男</label><label for="female"><input type="radio" id="female" name="sex" value="女" v-model="sex">女</label><h4>{{sex}}</h4><!-- 结合checkbok复选框 --><label for="one"><input type="checkbox" id="one" name="num" value="one" v-model="nums">one</label><label for="two"><input type="checkbox" id="two" name="num" value="two" v-model="nums">two</label><h4>{{nums}}</h4><!-- checkbox也可以做单选框,比如注册时的同意条款 --><!-- 经试验如果绑定的data类型是个数组,选中与否的值和value有关,如果是个字符串,只会出现布尔值 --><label for="agree"><input type="checkbox" id="agree" name="agree" value="" v-model="isAgree">同意条款</label><h4>{{'是否同意条款:'}}{{isAgree}}</h4><button @click="nextBtnClick1">验证是否选中协议</button><button :disabled="!isAgree">或者不同意不能点</button><br><!-- 结合select类型 --><!-- 向服务器提交时,name就会变成k-v中的k --><!-- select的v-model标签是写在select上,不是option上 --><select name="fruit" id="fruit" v-model="fruit"><option value="apple">apple</option><option value="pear">pear</option><option value="banana">banana</option><option value="orange">orange</option></select><h4>{{fruit}}</h4><!-- 多选 --><!-- 标签id不能重复 --><!-- 多选要加multiple标签 --><!-- data里用数组和字符串渲染结果是一样的 --><select name="fruits" id="fruits" v-model="fruits" multiple><option value="apple">apple</option><option value="pear">pear</option><option value="banana">banana</option><option value="orange">orange</option></select><h4>{{fruits}}</h4><!-- 使用data中的数据动态生成选项 --><!-- radio单选框案例 --><div><label :for="hobby" v-for="hobby in hobbies"><input type="radio" :id="hobby" name="radioSelectedHobby" :value="hobby" v-model="radioSelectedHobby">{{hobby}}</label></div>{{radioSelectedHobby}}<!-- checkbox复选框 --><div><label :for="hobby" v-for="hobby in hobbies"><input type="checkbox" :id="hobby" name="checkboxSelectedHobbies" :value="hobby"v-model="checkboxSelectedHobbies">{{hobby}}</label></div>{{checkboxSelectedHobbies}}<!-- select下拉选择框 --><!-- 单选 --><div><select name="selectedHobby" id="selectedHobby" v-model="selectSelectedHobby"><option v-for="hobby in hobbies" :value="hobby">{{hobby}}</option></select></div>{{selectSelectedHobby}}<!-- 多选 --><div><select name="selectedHobbies" id="selectedHobbies" v-model="selectSelectedHobbies" multiple><option v-for="hobby in hobbies" :value="hobby">{{hobby}}</option></select></div>{{selectSelectedHobbies}}</div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {message1: 'v-model被绑定的数据',message2: '通过原理手动实现的被绑定的数据',sex: '男',nums: [],isAgree: '',fruit: 'pear',fruits: [],hobbies: ['basketball', 'sockerball', 'baseball', 'badminten'],radioSelectedHobby: 'basketball',checkboxSelectedHobbies: [],selectSelectedHobby: 'basketball',selectSelectedHobbies: []},methods: {input(event) {this.message2 = event.target.value},nextBtnClick1() {if (this.isAgree != true) {alert("没选")} else {alert("选了")}}},computed: {},filters: {}})</script>
</body></html>

v-model 修饰符的使用:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="app"><input type="text" v-model="message"><h4>{{message}}</h4><!-- .lazy只会在失去焦点和回车时绑定 --><input type="text" v-model.lazy="message"><br><!-- input的类型设为number,只能输入数字,但v-model的特性会让所有输入的东西变字符串类型,想保持数字类型,就要使用.number,注意下图1中number1和number2的类型差别 --><input type="number" v-model="number1"><h4>{{number1}}--{{typeof number1}}</h4><input type="number" v-model.number="number2"><h4>{{number2}}--{{typeof number2}}</h4><!-- .trim剥除两边空格 --><!-- 当输入很多空格时虽然在输出上面看不出来,那是因为浏览器处理了,但其实真实的data是有很多空格的,见下图2,使用.trim就会去掉两边的空格,中间的空格不会处理--><input type="text" v-model="text1"><h4>{{text1}}</h4><input type="text" v-model.trim="text2"><h4>{{text2}}</h4></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: "#app",data: {message: 'message-context',number1: 0,number2: 0,text1: '',text2: ''},methods: {},computed: {},filters: {}})</script>
</body></html>


Vue.js 2.x 教程(1)相关推荐

  1. (私人收藏)Vue.js手册及教程

    (私人收藏)Vue.js手册及教程 https://pan.baidu.com/s/1XG1XdbbdBQm7cyhQKUIrRQ 5lrt Vue.js手册及教程Vue.js 教程Vue.js 安装 ...

  2. Node.js (v19.1.0npm 8.19.3) vue.js安装配置教程(超详细)

    Node.js (v19.1.0npm 8.19.3) vue.js安装配置教程(超详细) 目录 一.安装Node(npm)需要的环境和版本发布信息 (1).Node版本和npm版本关系 (2).支持 ...

  3. Vue.js安装使用教程

    一.说明 上大学前,请的都是前端JavaScript.后端ASP/PHP/JSP.前后端代码混杂:上大学时,请的都是前端Jquery.后端SSH.前后端代码分离通过模板关联:大学出来后,请的都是前端三 ...

  4. vue.js 2.x教程

    教程 基础 安装 兼容性 Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性.但它支持所有兼容 ECMAScript 5 的浏览器. 更新日志 ...

  5. Vue.js 2.x 教程(2)

    由于本vue教程的参考视频太旧,不再更新,请移步新版尚硅谷Vue技术全家桶(1) 组件化 组件化概念: 注:组件化和模块化是有区别的 组件的基本使用步骤 组件初步接触: <!DOCTYPE ht ...

  6. Vue.js入门系列教程(二)

    过滤器:filter 全局过滤器 <!DOCTYPE html> <html lang="en"><head><meta charset= ...

  7. Vue.js官网版教程

    前言 这是vue官网案例学习,记录一下 序言 vue.js介绍 Vue.js 渐进式 JavaScript 框架 https://learning.dcloud.io/#/?vid=0 第1节 安装与 ...

  8. Vue.js 系列教程 3:Vue-cli,生命周期钩子

    原文:intro-to-vue-3-vue-cli-lifecycle-hooks 译者:nzbin 这是 JavaScript 框架 Vue.js 五篇教程的第三部分.在这一部分,我们将学习 Vue ...

  9. Vue.js 系列教程 4:Vuex

    原文:intro-to-vue-4-vuex 译者:nzbin 这是关于 JavaScript 框架 Vue.js 五个教程的第四部分.在这一部分,我们会学习使用 Vuex 进行状态管理.这个系列教程 ...

最新文章

  1. 计算机网络第二章:物理层
  2. oledb 获取所有表的名字和列名
  3. python中双冒号_c++中冒号(:)和双冒号(::)的用法和c/c++ 位域结构体
  4. SAP CRM One order appointment duration table
  5. Table.Rows.Remove(dr)和Table.Delete()的区别
  6. 重大技术突破首次发布!十问解密云栖大会!
  7. JAVA SAX解析XML文档
  8. 64位电脑mysql_Windows 64位操作系统下安装和配置MySQL
  9. 有意思的《致招商银行的公开信》行动!
  10. 如何遍历或枚举JavaScript对象?
  11. python自定义修饰器_Python进阶自检清单:来自《Effective Python》的建议(二)
  12. 砍价小程序怎么变成二维码(小程序码)
  13. php网站设计思路,PHP开发之网页留言板的思路及设计
  14. 【下载工具】哔哩哔哩视频下载器——(Downkyi)下载姬v1.3.3
  15. 智能电视如何测试软件,智能电视屏幕如何快速识别好坏?教你几招!
  16. 【AUTOSAR】【CAN通信】CanTrcv
  17. FIN_WAIT_2状态解释
  18. 罗辑思维八里庄沙龙:Cloud Native 的演进(—)--从零开始了解云原生架构
  19. R语言学习手记 (1)
  20. 好压压缩文件目录乱码的解决

热门文章

  1. c语言中文渲染库,GLSL渲染编程基础与实例 (C#版本) 中文pdf扫描版[136MB]
  2. 【前端重构技能天赋】(二)——Javascript、CSS篇
  3. Unity实现触摸屏手势控制镜头旋转与缩放
  4. android 字符串折线图,Android + MPAndroidChart 实现折线、柱形和饼状图
  5. [家里蹲大学数学杂志]第048期普林斯顿高等研究所的疯子们
  6. dnf 跨服 服务器 位置,DNF新跨区终于来到 再也不用担心频道爆满了
  7. typescript用什么软件写_用TypeScript写了个低配版H5美图工具
  8. 如何在同一IP号不同端口的服务器之间复制文件
  9. html css画小猪佩琪,【前端切图】用css画一个卡通形象-小猪佩奇
  10. java入门 常见问题0007:如何让JTextField文本框可以设置背景图像