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;
Angular: Google收购的前端框架,由一群Java程序员开发,其特点是将后台的MVC模式搬到了前端并增加了模块化开发的理念,与微软合作,采用TypeScript语法开发;对后台程序员友好,对前端程序员不太友好;最大的缺点是版本迭代不合理(如: 1代-> 2代,除了名字,基本就是两个东西;截止发表博客时已推出了Angular6)
React: Facebook出品,一款高性能的JS前端框架;特点是提出了新概念[虚拟DOM]用于减少真实DOM操作,在内存中模拟DOM操作,有效的提升了前端渲染效率;缺点是使用复杂,因为需要额外学习一门[JSX] 语言;
Vue:一款渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性。其特点是综合了Angular (模块化)和React (虚拟DOM)的优点;
Axios :前端通信框架;因为Vue 的边界很明确,就是为了处理DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接选择使用jQuery提供的AJAX通信功能;
前端三大框架:Angular、React、Vue
ES6语法
1.不一样的变量声明:const和let
ES6推荐使用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 在声明时必须被赋值
2.模板字符串
在ES6之前,我们往往这么处理模板字符串:
通过"\"和"+"来构建模板
$("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();// default
5.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 = 0o10;console.log(oValue); // 8 let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`console.log(bValue); // 2
7.对象和数组解构
// 对象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 Child
9.for...of 和 for...in
for...of 用于遍历一个迭代器,如数组:
let letters = ['a', 'b', 'c'];letters.size = 3;for (let letter of letters) { console.log(letter);}// 结果: a, b, c
for...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 关键词
1、基本认识vue
- 轻量级,体积小是一个重要指标。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安装
初识vue.js
<body> <div id="app">{{message}}</div> //执行到这里显然出对应的HTML <script src="../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 层通过接口请求进行数据交互,起呈上启下作用。
如下图所示:
简单画了一张图来说明 MVVM 的各个组成部分:
分层设计一直是软件架构的主流设计思想之一,MVVM 也不例外。
View 层
View 是视图层,也就是用户界面。前端主要由 HTML 和 CSS 来构建,为了更方便地展现 ViewModel 或者 Model 层的数据,已经产生了各种各样的前后端模板语言,比如 FreeMarker、Marko、Pug、Jinja2等等,各大 MVVM 框架如 KnockoutJS,Vue,Angular 等也都有自己用来构建用户界面的内置模板语言。
Model 层
Model 是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,主要围绕数据库系统展开。后端的处理通常会非常复杂
ViewModel 层
ViewModel 是由前端开发人员组织生成和维护的视图数据层。在这一层,前端开发者对从后端获取的 Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。需要注意的是 ViewModel 所封装出来的数据模型包括视图的状态和行为两部分,而 Model 层的数据模型是只包含状态的,比如页面的这一块展示什么,那一块展示什么这些都属于视图状态(展示),而页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互),视图状态和行为都封装在了 ViewModel 里。这样的封装使得 ViewModel 可以完整地去描述 View 层。由于实现了双向绑定,ViewModel 的内容会实时展现在 View 层,这是激动人心的,因为前端开发者再也不必低效又麻烦地通过操纵 DOM 去更新视图,MVVM 框架已经把最脏最累的一块做好了,我们开发者只需要处理和维护 ViewModel,更新数据视图就会自动得到相应更新,真正实现数据驱动开发。看到了吧,View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与 Model 层交互,这就完全解耦了 View 层和 Model 层,这个解耦是至关重要的,它是前后端分离方案实施的重要一环。
Vue实例的options
- el:
类型 : string | HTMLElement
作用 : 决定之后Vue实例会管理哪一个DOM。 - data:
类型 : Object | Function (组件当中data必须是一个函数)
作用 : Vue实例对应的数据对象。 - methods:
类型 : { [key: string]: Function }
作用 : 定义属于Vue的一 些方法,可以在其他地方调用,也可以在指令中使用。
vue实例的生命周期
一、解析
1、什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!
2、生命周期钩子 = 生命周期函数 = 生命周期事件
3、主要的生命周期函数分类:
- 创建期间的生命周期函数:
+ beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
+ created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
+ beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
+ mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
- 运行期间的生命周期函数:
+ beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
+ updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
- 销毁期间的生命周期函数:
+ beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
+ destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
<body> <div id="app"> <input type="button" value="修改msg" @click="msg='No'"> <h3 id="h3">{{ msg }}</h3> </div> <script> // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { msg: 'ok' }, methods: { show() { console.log('执行了show方法') } }, beforeCreate() { // 这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它 console.log(this.msg) this.show() // 注意: 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化 }, created() { // 这是遇到的第二个生命周期函数 console.log(this.msg) this.show() // 在 created 中,data 和 methods 都已经被初始化好了! // 如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作 }, beforeMount() { // 这是遇到的第3个生命周期函数,表示 模板已经在内存中编辑完成了,但是尚未把 模板渲染到 页面中 console.log(document.getElementById('h3').innerText) // 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串 }, mounted() { // 这是遇到的第4个生命周期函数,表示,内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了 console.log(document.getElementById('h3').innerText) // 注意: mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动 }, // 接下来的是运行中的两个事件 beforeUpdate() { // 这时候,表示 我们的界面还没有被更新【数据被更新了吗? 数据肯定被更新了】 console.log('界面上元素的内容:' + document.getElementById('h3').innerText) console.log('data 中的 msg 数据是:' + this.msg) // 得出结论: 当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面尚未和 最新的数据保持同步 }, updated() { console.log('界面上元素的内容:' + document.getElementById('h3').innerText) console.log('data 中的 msg 数据是:' + this.msg) // updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的 } }); </script></body>
2、基本语法
1、插值操作
Mustache语法
<div id="app"> <h2>{{massage}}</h2> <h2>{{massage}},洛依尘</h2> <h2>{{firstName+lastName}}</h2> <h2>{{firstName+' '+lastName}}</h2> <h2>{{counter*2}}</h2></div><body> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: "#app", data: { massage: "你好", firstName:"kobe", lastName:"bryant", counter:200 } }) </script></body>
v-once指令
该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的
该指令表示元素和组件(组件后面才会学习)只渲染- 次,不会随着数据的改变而改变
<h2 v-once>{{massage}}</h2>
v-html
该指令后面往往会跟上一个string类型
会将string的html解析出来并且进行渲染
<h2>{{url}}</h2> <!-- <a href="www.baidu.com">百度一下</a> --> <h2 v-html="url"></h2> <!-- 百度一下 -->
v-text
都是用于将数据显示在界面中,但是通常只接受一个string类型
<h2 v-text="massage">,洛依尘</h2> <!--你好-->
v-pre
用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法
<h2 v-pre>{{massage}}</h2> <!-- {{massage}} -->
v-cloak
在某些情况下,f防止浏览器可能会直接显然出未编译的Mustache标签。
<style> [v-cloak] { display: none; } </style></head><div id="app" v-cloak> <h2>{{massage}}</h2> <h2 v-once>{{massage}}</h2> <h2>{{url}}</h2> <!-- <a href="www.baidu.com">百度一下</a> --> <h2 v-html="url"></h2> <!-- 百度一下 --> <h2 v-text="massage">,洛依尘</h2> <!--你好--> <h2 v-pre>{{massage}}</h2> <!-- {{massage}} --></div><body> <script src="../js/vue.js"></script> <script> //在vue解析之前,div里有一个属性c-cloak //在vue解析之后,div里没有一个属性c-cloak const app = new Vue({ el: "#app", data: { massage: "你好", url: '<a href="www.baidu.com">百度一下</a>' } }) </script></body>
2、绑定属性
v-bind
v-bind用于绑定一个或多个属性值,或者向另-一个组件传递props值
<div id="app"> <!-- <img src="{{imgURL}}" alt=""> --> <!-- 错误的用法:这里不可以使用mustache语法--> <!-- 正确用法:使用v-band指令 --> <a v-bind:href="aHref">百度</a> <img v-bind:src='imgURL' alt="" > <!-- 语法糖的写法 --> <a :href="aHref">百度</a> <img :src='imgURL' alt="" > </div><body> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: "#app", data: { massage: "你好", imgURL:'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png', aHref:"https://www.baidu.com/" } }) </script></body>
v-bind 动态绑定class(对象语法)
- 可以通过{ }绑定一个类
- 也可以通过判断,传入多个值
- 和普通类同时存在,并不冲突
- 如果过于复杂,可以放在一个methods或者computed中
<style> .active{ color: red; } </style></head><div id="app"> <!-- <h2 >{{massage}}</h2> <h2 :>{{massage}}</h2> --> <!-- <h2 :>{{massage}}</h2> 对class对象进行选择--> <h2 v-bind:>{{massage}}</h2> <!-- 将内容放在一个methods里,并调用 --> <h2 v-bind:>{{massage}}</h2> <button v-on:click="bntClick">按钮</button> <!-- 监听按钮,使用bntClick方法 --></div><body> <script src="../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 :>{{massage}}</h2> <h2 :>{{massage}}</h2> <h2 :>{{massage}}</h2></div><body> <script src="../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" : @click="liClick(index)"> <!-- {active: currentIndex === index}当currentIndex === index为true时,改变颜色 --> {{index}}.{{item}} </li> </ul></div><body> <script src="../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
<div id="app"> <!-- <h2 :>{{massage}}</h2> --> <!-- 这里要加' '要不然vue会去解析50px这个变量然后报错 --> <h2 :>{{massage}}</h2> <!-- finalSize当成一个变量在使用 --> <h2 :>{{massage}}</h2> <!-- 也可以拼接 --> <h2 :>{{massage}}</h2> <!-- 数组语法 --> <h2 :>{{massage}}</h2></div><body> <script src="../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="../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 =0 for (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="../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="../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="../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); } } }) // 如果我们函数需要参数,但是没有传入参数,那么函数的形参为undefined function 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="提交" @click.prevent='submitClick'> </form> <!-- 3. 监听某个键盘的键位 --> <input type="text" @keyup.enter="keyUp"> <!-- 4. once修饰符的使用 --> <button @click.once='bnt2Click'>按钮</button></div><body> <script src="../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="../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="../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 是什么?
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进行对比,然后更新视图
v-if和v-show的区别
v-show控制的是节点的display属性 v-if是将节点删除了 如果节点需要频繁显示隐藏 使用v-show性能更佳!
<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="../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="../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找到正确的位置区插入新的节点。
所以一句话, key的作用主要是为了高效的更新虚拟DOM。
原文转载:http://www.shaoqun.com/a/892314.html
跨境电商:https://www.ikjzd.com/
mil:https://www.ikjzd.com/w/1285
xinong:https://www.ikjzd.com/w/1368
barclays:https://www.ikjzd.com/w/2775
一款渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性。其特点是综合了Angular(模块化)和React(虚拟DOM)的优点;Vue.js学习笔记(一)目录Vue.js学习笔记(一)ES6语法1.不一样的变量声明:const和let2.模板字符串3.箭头函数(ArrowFunctions)4.函数的参数默认值5.Spread/Rest操作
麦言:https://www.ikjzd.com/w/1456
贝恩投资公司:https://www.ikjzd.com/w/1336
四川雨水减弱北方华南有分散性降水 南方高温持续北方变凉爽:http://www.30bags.com/a/433353.html
四川元素绚丽亮相_西安世界园艺博会开园 :http://www.30bags.com/a/410430.html
四川这5个"欧洲小镇" 如在法国旅游:http://www.30bags.com/a/422089.html
四川这个地方已种茶2000多年,还成为宫廷用茶,许多人不知道在哪:http://www.30bags.com/a/223864.html
强壮的公么征服我厨房 我在洗碗他在下面弄我:http://lady.shaoqun.com/m/a/248405.html
扒开屁股自己坐上来 男领导把我下面摸出水了:http://lady.shaoqun.com/m/a/248374.html
深圳宝安科技馆8月展览汇总(持续更新):http://www.30bags.com/a/517601.html
2021时尚深圳展蝶讯馆展览好看吗:http://www.30bags.com/a/517602.html
2021时尚深圳蝶讯馆观展攻略:http://www.30bags.com/a/517603.html
深圳欢乐谷夏浪音乐节有朱星杰吗:http://www.30bags.com/a/517604.html
No comments:
Post a Comment