一款渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性 。其特点是综合了Angular (模块化)和React (虚拟DOM)的优点;Vue.js学习笔记(一)
目录
- Vue.js学习笔记(一)
- ES6语法
- 1.不一样的变量声明:const和let
- 2.模板字符串
- 3.箭头函数(Arrow Functions)
- 4. 函数的参数默认值
- 5.Spread / Rest 操作符
- 6.二进制和八进制字面量
- 7.对象和数组解构
- 8.对象超类
- 9.for...of 和 for...in
- 10.ES6中的类
- 1、基本认识vue
- MVVM 模式
- View 层
- Model 层
- ViewModel 层
- Vue实例的options
- vue实例的生命周期
- MVVM 模式
- 2、基本语法
- 1、插值操作
- 2、绑定属性
- 3、计算属性
- 4、事件监听
- v-on的修饰符
- 5、条件判断
- Virtual DOM 是什么?
- Virtual DOM 作用是什么?
- v-if和v-show的区别
- v-for加key属性
- 哪些数组方法是响应式的
- 6、表单绑定
- v-model结合radio类型
- v-model结合select
- v-model的修饰符
- 综合-书籍购物车案例
- JS高阶函数
Vue 的核心库只关注视图层,方便与第三方库或既有项目整合 。
HTML + CSS + JS : 视图 :
给用户看,刷新后台给的数据网络通信 : axios
页面跳转 : vue-router
状态管理:vuex
Vue-UI : ICE , Element UI
- VUE 概述
Vue (读音/vju/, 类似于view)是一套用于构建用户界面的渐进式框架,发布于2014年2月 。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用 。Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库(如: vue-router: 跳转,vue-resource: 通信,vuex:管理)或既有项目整合 - 前端三要素
HTML (结构) :超文本标记语言(Hyper Text Markup Language) ,决定网页的结构和内容
CSS (表现) :层叠样式表(Cascading Style sheets) ,设定网页的表现样式
JavaScript (行为) :是一种弱类型脚本语言,其源代码不需经过编译,而是由浏览器解释运行,用于控制网页的行为 - JavaScript框架
jQuery: 大家熟知的JavaScript框架,优点是简化了DOM操作,缺点是DOM操作太频繁,影响前端性能;在前端眼里使用它仅仅是为了兼容IE6、7、8;
React: Facebook出品,一款高性能的JS前端框架;特点是提出了新概念[虚拟DOM]用于减少真实DOM操作,在内存中模拟DOM操作,有效的提升了前端渲染效率;缺点是使用复杂,因为需要额外学习一门[JSX] 语言;
Vue:一款渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性 。其特点是综合了Angular (模块化)和React (虚拟DOM)的优点;
Axios :前端通信框架;因为Vue 的边界很明确,就是为了处理DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接选择使用jQuery提供的AJAX通信功能;
前端三大框架:Angular、React、Vue
ES6语法1.不一样的变量声明:const和letES6推荐使用let声明局部变量,相比之前的var(无论声明在何处,都会被视为声明在函数的最顶部)
let和var声明的区别:
var x = '全局变量';{let x = '局部变量';console.log(x); // 局部变量}console.log(x); // 全局变量<body><button>按钮1</button><button>按钮2</button><button>按钮3</button><button>按钮4</button><button>按钮5</button><script>// 变量作用域:变量在什么位置内是可用的// ES5之前因为if和for都没有块级作用域的概念,所以在很多时候,我们都必须借助于function的作月域来解决应用外面变量的问题// 闭包可以解决这个问题: 函数是一个作用域// ES6中加入了let,let它是有if和for块级作用域// ES5语法// var btns = document.getElementsByTagName('button');// for(var i = 0; i<btns.length; i++){//(function(num){//bnts[num].addEventListener('click',function(){//console.log('第'+num+'个按钮被点击');//})//})(i)// }// ES6语法const btns = document.getElementsByTagName('button')for (let i = 1; i < btns.length; i++) {btns[i].addEventListener('click', function () {console.log('第' + i + '个按钮被点击');})}</script></body>let表示声明变量,而const表示声明常量,两者都为块级作用域;const 声明的变量都会被认为是常量,意思就是它的值被设置完成后就不能再修改了,且const定义标识符时,必须赋值:
建议:在ES6开发中,优先使用const,只有需要改变某一个标识符的时候才使用let 。
const a = 1a = 0 //报错如果const的是一个对象,对象所包含的值(内部属性)是可以被修改的 。抽象一点儿说,就是对象所指向的地址没有变就行:const student = { name: 'cc' }student.name = 'yy';// 不报错student= { name: 'yy' };// 报错有几个点需要注意:- let 关键词声明的变量不具备变量提升(hoisting)特性
- let 和 const 声明只在最靠近的一个块中(花括号内)有效
- 当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING
- const 在声明时必须被赋值
通过“\”和“+”来构建模板
$("body").html("This demonstrates the output of HTML \content to the page, including student's\" + name + ", " + seatNumber + ", " + sex + " and so on.");而对ES6来说- 基本的字符串格式化 。将表达式嵌入字符串中进行拼接 。用${}来界定;
- ES6反引号(``)直接搞定;
$("body").html(`This demonstrates the output of HTML content to the page, including student's ${name}, ${seatNumber}, ${sex} and so on.`);3.箭头函数(Arrow Functions)ES6 中,箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个 =>,紧接着是函数体;箭头函数最直观的三个特点 。
- 不需要 function 关键字来创建函数
- 省略 return 关键字
- 继承当前上下文的 this 关键字
// ES5var add = function (a, b) {return a + b;};// 使用箭头函数var add = (a, b) => a + b;// ES5[1,2,3].map((function(x){return x + 1;}).bind(this));// 使用箭头函数[1,2,3].map(x => x + 1);细节:当你的函数有且仅有一个参数的时候,是可以省略掉括号的 。当你函数返回有且仅有一个表达式的时候可以省略{} 和 return;4. 函数的参数默认值在ES6之前,我们往往这样定义参数的默认值:
// ES6之前,当未传入参数时,text = 'default';function printText(text) {text = text || 'default';console.log(text);}// ES6;function printText(text = 'default') {console.log(text);}printText('hello'); // helloprintText();// default5.Spread / Rest 操作符Spread / Rest 操作符指的是 ...,具体是 Spread 还是 Rest 需要看上下文语境 。当被用于迭代器中时,它是一个 Spread 操作符:
function foo(x,y,z) {console.log(x,y,z);} let arr = [1,2,3];foo(...arr); // 1 2 3当被用于函数传参时,是一个 Rest 操作符:当被用于函数传参时,是一个 Rest 操作符:function foo(...args) {console.log(args);}foo( 1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]6.二进制和八进制字面量ES6 支持二进制和八进制的字面量,通过在数字前面添加 0o 或者0O 即可将其转换为八进制值:let oValue = https://tazarkount.com/read/0o10;console.log(oValue); // 8 let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`console.log(bValue); // 27.对象和数组解构// 对象const student = {name: 'Sam',age: 22,sex: '男'}// 数组// const student = ['Sam', 22, '男'];// ES5;const name = student.name;const age = student.age;const sex = student.sex;console.log(name + ' --- ' + age + ' --- ' + sex);// ES6const { name, age, sex } = student;console.log(name + ' --- ' + age + ' --- ' + sex);8.对象超类ES6 允许在对象中使用 super 方法:var parent = {foo() {console.log("Hello from the Parent");}} var child = {foo() {super.foo();console.log("Hello from the Child");}} Object.setPrototypeOf(child, parent);child.foo(); // Hello from the Parent// Hello from the Child9.for...of 和 for...infor...of 用于遍历一个迭代器,如数组:let letters = ['a', 'b', 'c'];letters.size = 3;for (let letter of letters) {console.log(letter);}// 结果: a, b, cfor...in 用来遍历对象中的属性: let stus = ["Sam", "22", "男"]; for (let stu in stus) {console.log(stus[stu]);}// 结果: Sam, 22, 男10.ES6中的类ES6 中支持 class 语法,不过,ES6的class不是新的对象继承模型,它只是原型链的语法糖表现形式 。函数中使用 static 关键词定义构造函数的的方法和属性:
class Student {constructor() {console.log("I'm a student.");}study() {console.log('study!');}static read() {console.log("Reading Now.");}} console.log(typeof Student); // functionlet stu = new Student(); // "I'm a student."stu.study(); // "study!"stu.read(); // "Reading Now."类中的继承和超集:class Phone {constructor() {console.log("I'm a phone.");}} class MI extends Phone {constructor() {super();console.log("I'm a phone designed by xiaomi");}} let mi8 = new MI();extends 允许一个子类继承父类,需要注意的是,子类的constructor 函数中需要执行 super() 函数 。当然,你也可以在子类方法中调用父类的方法,如super.parentMethodName() 。
在 这里 阅读更多关于类的介绍 。
有几点值得注意的是:
- 类的声明不会提升(hoisting),如果你要使用某个 Class,那你必须在使用之前定义它,否则会抛出一个 ReferenceError 的错误
- 在类中定义函数不需要使用 function 关键词
- 轻量级,体积小是一个重要指标 。Vue.js 压缩后有只有 20多kb (Angular 压缩后 56kb+,React 压缩后 44kb+)
- 移动优先 。更适合移动端,比如移动端的 Touch 事件
- 易上手,学习曲线平稳,文档齐全
- 吸取了 Angular(模块化)和 React(虚拟 DOM)的长处,并拥有自己独特的功能,如:计算属性
- Vue是一个渐进式的框架可以将Vue作为你应用的一 部分嵌入其中,带来更丰富的交互体验 。
- 开源,社区活跃度高
- Vue有很多特点和Web开发中常见的高级功能
- 解耦视图和数据.
- 可复用的组件
- 前端路由技术
- 状态管理
- 虚拟DOM
- 开发版本
包含完整的警告和调试模式:https://vuejs.org/js/vue.js
删除了警告,30.96KB min + gzip:https://vuejs.org/js/vue.min.js - CDN
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>- NPM安装
<body><div id="app">{{message}}</div> //执行到这里显然出对应的HTML<script src="https://tazarkount.com/js/vue.js"></script><script>//执行这里创建Vue实例,并且对原HTML进行解析和修改 。//编程范式:声明式编程const app = new Vue({//创建Vue实例el:'#app',//用于指定要挂载的元素data:{//定义数据message:"洛依尘!"}})//元素js的做法(编程范式:命令式编程)// 1.创建div元素,设置id属性// 2.定义一个变量叫message// 3.将message变量放在前面的div元素中显示</script></body>MVVM 模式MVVM 源自于经典的 Model–View–Controller(MVC)模式(期间还演化出了 Model-View-Presenter(MVP)模式,可忽略不计) 。MVVM 的出现促进了 GUI 前端开发与后端业务逻辑的分离,极大地提高了前端开发效率 。MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用 。如下图所示:
文章插图
v-bind 动态绑定class(对象语法)
- 可以通过{ }绑定一个类
- 也可以通过判断,传入多个值
- 和普通类同时存在,并不冲突
- 如果过于复杂,可以放在一个methods或者computed中
<style>.active{color: red;}</style></head><div id="app"> <!-- <h2 class="active">{{massage}}</h2><h2 :class="active">{{massage}}</h2> --><!-- <h2 :class="{类名1:ture,类名2:boolean}">{{massage}}</h2> 对class对象进行选择--><h2 v-bind:class="{active: isActive , line: isLine}">{{massage}}</h2><!-- 将内容放在一个methods里,并调用 --><h2 v-bind:class="getClasses()">{{massage}}</h2><button v-on:click="bntClick">按钮</button><!-- 监听按钮,使用bntClick方法 --></div><body> <script src="https://tazarkount.com/js/vue.js"></script> <script>const app = new Vue({el: "#app",data: {massage: "你好",active:'active',isActive:true,//设置boolean值决定是否启用isLine:true},methods:{bntClick: function(){this.isActive=!this.isActive},getClasses:function(){return {active: this.isActive, line: this.isLine}}}}) </script></body>v-bind 动态绑定class(数组语法)<div id="app"><!-- 如果在[]数组里的元素加了引号,代表他是一个字符串,而不是引用一个变量 --><h2 :class="[active,line]">{{massage}}</h2><h2 :class="['active','line']">{{massage}}</h2><h2 :class="getClasses()">{{massage}}</h2></div><body> <script src="https://tazarkount.com/js/vue.js"></script> <script>const app = new Vue({el: "#app",data: {massage: "你好",active:"aaa",line:"bbb"},methods:{getClasses:function(){return [this.active,this.line]}}}) </script></body>小作业:点击列表中的哪一项, 那么该项的文字变成红色<style>.active {color: red;} </style></head><div id="app"> <ul><li v-for="(item, index) in movies" :class="{active: currentIndex === index}" @click="liClick(index)"><!-- {active: currentIndex === index}当currentIndex === index为true时,改变颜色-->{{index}}.{{item}}</li> </ul></div><body> <script src="https://tazarkount.com/js/vue.js"></script> <script>const app = new Vue({el: "#app",data: {movies: ['海王', '火影忍者', '进击的巨人', '死神'],currentIndex: 0},methods: {liClick(index) {this.currentIndex = index}}}) </script></body>v-bind 绑定style【一 两万字Vue.js基础学习笔记】
<div id="app"> <!-- <h2 :style="{key(属性名):value(属性值)}">{{massage}}</h2> --><!-- 这里要加' '要不然vue会去解析50px这个变量然后报错 --><h2 :style="{fontSize: '50px'}">{{massage}}</h2><!-- finalSize当成一个变量在使用 --><h2 :style="{fontSize: finalSize}">{{massage}}</h2><!-- 也可以拼接 --><h2 :style="{fontSize: finalSize + 'px',color:finalColor}">{{massage}}</h2><!-- 数组语法 --><h2 :style="[baseStyle,baseStyle1]">{{massage}}</h2></div><body> <script src="https://tazarkount.com/js/vue.js"></script> <script>const app = new Vue({el: "#app",data: {massage: "你好",finalSize: 100,finalColor: 'red',baseStyle:{color:'red'},baseStyle1:{fontSize:'75px'}}}) </script></body>3、计算属性一、什么是计算属性模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的 。在模板中放入太多的逻辑会让模板过重且难以维护 。
二、计算属性的用法
在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以 。
<div id="app"> <h2>{{firstName+' '+lastName}}</h2><h2>{{fullName}}</h2><h2>总价格:{{totalPrice}}</h2></div><body> <script src="https://tazarkount.com/js/vue.js"></script> <script>const app = new Vue({el: "#app",data: {firstName:"luo",lastName:"yichen",books:[{id:100, name: 'java核心技术' , price:100},{id:101, name: 'c核心技术' , price:100},{id:102, name: 'php核心技术' , price:100},{id:103, name: 'python核心技术' , price:100}]},// computed: 计算属性()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;}}}) </script>计算属性的getter和setter每个计算属性都包含一个getter和一个setter
- 在上面的例子中,我们只是使用getter来读取 。
- 在某些情况下,你也可以提供一个setter方法 (不常用) 。
- 在需要写setter的时候,代码如下: .
<div id="app"> <h2>{{fullName}}</h2></div><body> <script src="https://tazarkount.com/js/vue.js"></script> <script>const app = new Vue({el: "#app",data: {firstName: "luo",lastName: "yichen",},computed: {// fullName: function () {//return this.firstName + ' ' + this.lastName// }// 计算属性一般没有set值,只读属性 。fullName:{set: function(newValue){const names = newValue.split(" ");this.firstName = names[0];this.lastName = names[1];},get: function(){return this.firstName + ' ' + this.lastName}},// 简洁写法// fullName:function(){//return this.firstName+' '+this.lastName// }}}) </script></body>计算属性与methods对比<div id="app"><!-- 通过拼接:语法过于繁琐 --><h2>{{firstName}} {{lastName}}</h2><!-- 通过定义methods 每次都要调用--><h2>{{getFullName()}}</h2><!-- 通过computed 如果没有发生改变只需要调用一次--><h2>{{fullName}}</h2></div><body><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {firstName: "luo",lastName: "yichen"},methods: {getFullName: function () {return this.firstName + ' ' + this.lastName}},computed: {fullName: function () {return this.firstName + ' ' + this.lastName}}})</script></body>4、事件监听可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码 。获取到浏览器参数的event对象: $event
<div id="app"> <h2>{{counter}}</h2><button v-on:click="increment">+</button><button v-on:click="decrement">-</button><!-- 语法糖 当没参数时()可以不用写 --><button @click="increment">+</button><button @click="decrement">-</button><!-- 事件调用时没有参数 --><button @click="bnt1Click()">按钮1</button><button @click="bnt1Click">按钮1</button><!-- 在事件定义前,写函数省略了小括号,但是方法本身需要一个参数,这个时候Vue会将浏览器默认生成的event事件对象作为参数传入方法中 --><button @click="bnt2Click(123)">按钮2</button><button @click="bnt2Click()">按钮2</button><button @click="bnt2Click">按钮2</button><!-- 定义方法时,我们需要event对象,同时又需要其他参数 --><!-- 在调用方式时,如何手动的获取到浏览器参数的event对象: $event --><button @click="bnt3Click('abc',$event)">按钮3</button></div><body> <script src="https://tazarkount.com/js/vue.js"></script> <script>const app = new Vue({el: "#app",data: {counter: 0},methods:{increment(){this.counter++},decrement(){this.counter--},bnt1Click(){console.log("bnt1Click");},bnt2Click(abc){console.log("--------------",abc);},bnt3Click(abc,event){console.log("++++++++++++++", abc,event);}}})// 如果我们函数需要参数,但是没有传入参数,那么函数的形参为undefinedfunction abc(name){console.log(name);}abc() </script></body>v-on的修饰符- .stop修饰符的使用
当多对标签进行重叠的时候, 你点击最上面的一层标签的时候, 会自动的冒泡到他下面的所有标签上面
而.stop就是阻止冒泡使用的
- .prevent修饰符的使用
在form表单提交时候或者在点击a标签的时候, 会阻止提交或跳转
- .keyup监听某个键盘的键帽
监听某个键盘的键位
- .once修饰符的使用
绑定后只会触发一次
<div id="app"><!-- 1. .stop --><div @click='divClick'>aaaaa<button @click.stop='bntClick'>按钮</button></div><!-- 2. .prevent--><form action="baidu"><input type="submit" value="https://tazarkount.com/read/提交" @click.prevent='submitClick'></form><!-- 3. 监听某个键盘的键位 --><input type="text" @keyup.enter="keyUp"><!-- 4. once修饰符的使用 --><button @click.once='bnt2Click'>按钮</button></div><body><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {massage: "你好"},methods: {bntClick() {console.log('bnt')},divClick() {console.log('div')},submitClick() {console.log("submitClick")},keyUp() {console.log("up")},bnt2Click() {console.log('bnt2');}}})</script></body>5、条件判断v-if的原理:v-if后面的条件为false时,对应的元素以及其子元素不会渲染 。
也就是根本没有不会有对应的标签出现在DOM中 。
<div id="app"><h2 v-if="score>90">优秀</h2><h2 v-else-if="score>80">良好</h2><h2 v-else-if="score>60">及格</h2><h2 v-else>不及格</h2><h1>{{result}}</h1><h2 v-if="isShow">{{massage}}</h2><h1 v-else>当isShow为false时显示我</h1></div><body><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {massage: "你好",isShow: true,score: 99},computed: {result() {let showMessage = '';if (this.score >= 90) {showMessage = "优秀"} else if (this.score >= 80) {showMessage = "良好"}// ...return showMessage}}})</script></body>用户切换的小案例<div id="app"> <span v-if="isUser"><label for="username">用户账号</label><input type="text" id="username" placeholder="用户账号" key='username'></span><span v-else><label for="emailname">用户邮箱</label><input type="text" id="emailname" placeholder="用户邮箱" key='emailname'></span><button @click="isUser = !isUser">切换类型</button></div><body> <script src="https://tazarkount.com/js/vue.js"></script> <script>const app = new Vue({el: "#app",data: {isUser:true}}) </script></body>小问题:- 如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容 。
- 但是按道理讲,我们应该切换到另外一个input元素中了 。
- 在另一个input元素中,我们并没有输入内容 。
- 为什么会出现这个问题呢?
- 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素 。
- 在上面的案例中, Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了.
- 如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key
- 并且我们需要保证key的不同

文章插图
Virtual DOM 其实就是一棵以 JavaScript 对象( VNode 节点)作为基础的树,用对象属性来描述节点,实际上它只是一层对真实 DOM 的抽象 。最终可以通过一系列操作使这棵树映射到真实环境上 。
简单来说,可以把Virtual DOM 理解为一个简单的JS对象,并且最少包含标签名( tag)、属性(attrs)和子元素对象( children)三个属性 。不同的框架对这三个属性的命名会有点差别 。
对于虚拟DOM,咱们来看一个简单的实例,就是下图所示的这个,详细的阐述了
模板 → 渲染函数 → 虚拟DOM树 → 真实DOM的一个过程
文章插图
Virtual DOM 作用是什么?虚拟DOM的最终目标是将虚拟节点渲染到视图上 。但是如果直接使用虚拟节点覆盖旧节点的话,会有很多不必要的DOM操作 。例如,一个ul标签下很多个li标签,其中只有一个li有变化,这种情况下如果使用新的ul去替代旧的ul,因为这些不必要的DOM操作而造成了性能上的浪费 。
为了避免不必要的DOM操作,虚拟DOM在虚拟节点映射到视图的过程中,将虚拟节点与上一次渲染视图所使用的旧虚拟节点(oldVnode)做对比,找出真正需要更新的节点来进行DOM操作,从而避免操作其他无需改动的DOM 。
其实虚拟DOM在Vue.js主要做了两件事:
- 提供与真实DOM节点所对应的虚拟节点vnode
- 将虚拟节点vnode和旧虚拟节点oldVnode进行对比,然后更新视图
<div id="app"><!-- v-if: 当条件为false时,包含v-if指令的元素,根本就不会存在dom中 --><h2 v-if='isShow' id="aaa">{{massage}}</h2><!-- V- show:当条件为false时,v-show只是给我们的元素添加一个行内样式: display: none --><h2 v-show='isShow' id="bbb">{{massage}}</h2></div><body><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {massage: "你好",isShow: true}})</script></body>6、循环遍历当我们有一组数据需 要进行渲染时,我们就可以使用v-for来完成 。
v-for的语法类似于JavaScript中的for循环 。
格式如下: item in items的形式 。
<div id="app"><!-- 1.在遍历的过程中,没有使用索引值(下标值) --><ul><li v-for='item in names'>{{item}}</li></ul><!-- 2.在遍历过程中,获取索引值 --><ul><li v-for='(item,index) in names'>{{index+1}}.{{item}}</li></ul><!-- 1.在遍历对象的过程中,如果只是获取一个值,那么获取到的是value --><ul><li v-for="item in info">{{item}}</li></ul><!-- 2., 获取key和value 格式(value,key) --><ul><li v-for="(value,key) in info">{{value}}-{{key}}</li></ul><!-- 3. 获取key和value和index 格式(value,key,index)--><ul><li v-for="(value,key,index) in info">{{value}}-{{key}}-{{index}}</li></ul></div><body><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {names: ['why', 'who', 'what', 'where'] //遍历数组},info: {//遍历对象name: 'lyc',age: 18,height: 1.88}})</script></body>v-for加key属性- 为什么需要这个key属性呢(了解) ?
- 这个其实和Vue的虚拟DOM的Diff算法有关系 。
- 这里我们借用React' S diff algorithm中的一张图来简单说明一下:
- 当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一一个新
的节点
- 我们希望可以在B和C之间加一一个F , Diff算法默认执行起来是这样的 。
- 即把C更新成F , D更新成C , E更新成D ,最后再插入E ,是不是很没有
效率?
- 所以我们需要使用key来给每个节点做一个唯一标识
- Diff算法就可以正确的识别此节点
- 0找到正确的位置区插入新的节点 。
- Diff算法就可以正确的识别此节点

文章插图

文章插图
哪些数组方法是响应式的
<body><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {letters: ['A', 'C', 'B', 'D', 'E']},methods: {btnClick() {// 1.push()在数组最后添加元素this.letters.push('aaa','bbb')// 2.pop()在数组最后删除一个元素this.letters.pop();// 3.shift()删除在数组第一个元素this.letters.shift();// 4.unshift() 在数组最前面添加元素this.letters.unshift('ddd','ddd');// 5.splice()删除/插入/替换元素// 删除元素: 第一参数传入你从第几个元素开始删除,第二参数传入你要删除的几个元素(如果没有传,就删除后面所有元素)// 插入元素: 第二个传入0,后面跟上要添加的值// 替换元素: 第二参数传入你要删除元素,后面追加你要写入的元素完成替换this.letters.splice(1,3,'m','n','l')// 6.sort()排序this.letters.sort()// 7.reverse()反转this.letters.reverse()// 注意:通过索引值直接来修改数组中的元素 不是响应式// this.letters[0]='bbbbbbbbbbbb'// set(要修改的对象,索引值,修改后的值)Vue.set(this.letters,0,'bbbbbb')}}})// 扩展知识:可变参数// function sum(...sum){//console.log(sum);// }// sum(11,223,44,56,77,889,9,1)</script></body>6、表单绑定- 表单控件在实际开发中是非常常见的 。特别是对于用户信息的提交,需要大量的表单 。
- Vue中使用v-model指令来实现表单元素和数据的双向绑定 。
<body><div id="app"><input type="text" v-model="massage">{{massage}}</div><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {massage: "你好"}})</script></body>- 当我们在输入框输入内容时
- 因为input中的v-model绑定了message ,所以会实时将输入的内容传递给message , message发生改变 。
- 当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变 。
- 所以,通过v-model实现了双向的绑定 。
<div id="app"><!-- <input type="text" v-model="massage"> --><!-- <input type="text" :value="https://tazarkount.com/read/massage" @input="valueChange"> --><input type="text" :value="https://tazarkount.com/read/massage" @input="massage = $event.target.value">{{massage}}</div><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {massage: "你好"},methods: {valueChange(event) {this.massage = event.target.value;}}})</script></body>v-model结合radio类型<div id="app"><label for=""><input type="radio" id="male" value="https://tazarkount.com/read/男" v-model="sex">男</label><label for=""><input type="radio" id="female" value="https://tazarkount.com/read/女" v-model="sex">女</label><h2>{{sex}}</h2></div><body><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {message: "你好",sex:'男'}})</script></body>v-model结合checkbox类型单个勾选框: .
- v-modelI即为布尔值 。
- 此时input的value并不影响v-model的值 。
- 多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组 。
- 当选中某一个时 ,就会将input的value添加到数组中 。
<div id="app"><!-- 单选框 --><!-- <label for="agree"><input type="checkbox" id="agree" v-model="isAgree">同意协议</label><h2>{{isAgree}}</h2><button :disabled="!isAgree">下一步</button> --><!-- 多选框 --><!-- <input type="checkbox" value="https://tazarkount.com/read/篮球" v-model="hobbies">篮球<input type="checkbox" value="https://tazarkount.com/read/足球" v-model="hobbies">足球<input type="checkbox" value="https://tazarkount.com/read/排球" v-model="hobbies">排球<input type="checkbox" value="https://tazarkount.com/read/手球" v-model="hobbies">手球<h2>{{hobbies}}</h2> --><label v-for="item in originHobbies" :for="item"><input type="checkbox" :value="https://tazarkount.com/read/item" :id="item" v-model="hobbies">{{item}}</label></div><body><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {message: "你好",isAgree: false,//单选框hobbies:[],//多选框originHobbies:['篮球','足球','乒乓球','台球','高尔夫球']//也可以通过值绑定来从服务器获取值}})</script></body>v-model结合select单选:只能选中一个值 。- v-model绑定的是一个值 。
- 当我们选中option中的一个时,会将它对应的value赋值到mySelect中
- v-model绑定的是一个数组 。
- 当选中多个值时,就会将选中的option对应的value添加到数组mySelects中
<body><div id="app"><!-- 1、选择一个 --><select name="abc" id=""v-model="fruit"><option value="https://tazarkount.com/read/苹果">苹果</option><option value="https://tazarkount.com/read/香蕉">香蕉</option><option value="https://tazarkount.com/read/榴莲">榴莲</option><option value="https://tazarkount.com/read/西瓜">西瓜</option></select><h2>{{fruit}}</h2><!-- 2、选择多个 --><select name="abc" id=""v-model="fruits" multiple><option value="https://tazarkount.com/read/苹果">苹果</option><option value="https://tazarkount.com/read/香蕉">香蕉</option><option value="https://tazarkount.com/read/榴莲">榴莲</option><option value="https://tazarkount.com/read/西瓜">西瓜</option></select><h2>{{fruits}}</h2></div><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {message: "你好",fruit:"香蕉",fruits:[]}})</script></body>v-model的修饰符lazy修饰符:- 默认情况下, v- model默认是在input事件中同步输入框的数据的 。
- 也就是说, 一旦有数据发生改变对应的data中的数据就会自动发生
改变 。 - lazy修饰符可以让数据在失去焦点或者回车时才会更新:
- 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被
当做字符串类型进行处理 。 - 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数
字处理 。 - number修饰符可以让在输入框中输入的内容自动转成数字类型:
- 如果输入的内容首尾有很多空格,通常我们希望将其去除
- trim修饰符可以过滤内容左右两边的空格
<div id="app"><!-- 1.修饰符:lazy --><input type="text" v-model.lazy="message"><h2>{{message}}</h2><!-- 2.修饰符:number --><input type="number" v-model.number="age"><h2>{{typeof age}}</h2><!-- 3.修饰符:trim --><input type="text" v-model.trim="name"><h2>{{name}}</h2></div><body><script src="https://tazarkount.com/js/vue.js"></script><script>const app = new Vue({el: "#app",data: {message: "你好",age:12,name:''}})</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><link rel="stylesheet" href="https://tazarkount.com/read/style.css"></head><body><div id="app"><div v-if="books.length"><table><thead><tr><th></th><th>书籍名称</th><th> 出版日期</th><th> 价格</th><th> 购买数量</th><th> 操作</th></tr></thead><tbody><tr v-for="(item,index) in books"><td>{{item.id}}</td><td>{{item.name}}</td><td>{{item.date}}</td><td>{{item.price | showPrice}}</td><td><button @click="decrement(index)" v-bind:disabled="item.count <= 1">-</button>{{item.count}}<button @click="increment(index)">+</button></td><td><button @click="removeHandler(index)">移除</button></td></tr></tbody></table><h2>总价格: {{totalPrice | showPrice}}</h2></div><div v-else><h1>购物车为空</h1></div></div><script src="https://tazarkount.com/js/vue.js"></script><script src="https://tazarkount.com/read/main.js"></script></body></html>- CSS
table{border: 1px solid #000;border-collapse: collapse;border-spacing: 0;}th,td{padding: 8px 16px;border: 1px solid #000;text-align: left;}th{background-color: #f7f7f7;color: #5c6b77;font-weight: 600;}- JS
const app = new Vue({el: "#app",data: {books: [{id: 1,name: '《算法导论》',date: "2006-9",price: 85.00,count: 1},{id: 2,name: '《算法导论》',date: "2006-9",price: 85.00,count: 1},{id: 3,name: '《算法导论》',date: "2006-9",price: 85.00,count: 1},{id: 4,name: '《算法导论》',date: "2006-9",price: 85.00,count: 1}]},methods: {// getFinalPrice(price){//return '¥'+price.toFixed(2) //toFixed(2)保留两位小数// }increment(index) {this.books[index].count++},decrement(index) {this.books[index].count--},removeHandler(index) {this.books.splice(index, 1)}},filters: { //过滤器showPrice(price) {return '¥' + price.toFixed(2)}},computed: {totalPrice() {let totalPrice = 0;for (let i = 0; i < this.books.length; i++) {totalPrice += this.books[i].price * this.books[i].count;}return totalPrice;}}})JS高阶函数编程范式:命令式编程/声明式编程编程范式:面向对象编程(第一公民:对象)/函数式编程(第一公民:函数)
filter/map/reduce
filter中的回调函数有一个要求:必须返回一个 boolean值
true:当返回true时,函数内部会自动将这次回调的n加入到新的数组中
false:当返回false时,函数内部会过滤掉这次的n
- 基本写法
const nums = [10,20,111,222,444,40,50]// 1.需求:取出小于100的数字let newNums = []for(let n of nums){if(n > 100){newNums.push(n)}}// 2.需求:将所有小于160的数字进行转化:全部*2let new2Nums = []for(let n of newNums){new2Nums.push(n*2)}// 3.需求:将所有new2Nums数字相加,得到最终的记过let total = 0for(let n of new2Nums){total +=n}console.log(total)- 高阶写法
const nums = [10,20,111,222,444,40,50]// 1.filter函数的使用let newNums = nums.filter(function(n){return n<100})console.log(newNums)// 2.map函数的使用let new2Nums = newNums.map(function(n){return n*2})console.log(new2Nums)// 3.reduce函数的使用// reduce作用对数组中所有的内容进行汇总let total = new2Nums.reduce(function(preValue,n){return preValue + n;},0)console.log(total)// 第一次: revalue 0n 20// 第二次: revalue 20 n 40// 第二次: revalue 60 n 80// 第二次: revalue 140 n 100// 240- 高阶综合写法
const nums = [10,20,111,222,444,40,50]// 综合let total = nums.filter(function(n){return n<100}).map(function(n){return n*2}).reduce(function(preValue,n){return preValue + n;},0) //初始化console.log(total)//使用箭头函数进一步简化let total = nums.filter(n => n<100).map(n => n*2).reduce((pre,n) => pre+n)console.log(total)点击转跳第二部分内容- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
