文章目录

  • VUE笔记-01基础
    • 1、简介
      • mvvm
      • ES6补充
        • js高阶函数
        • let/var
        • const
        • 增强字面量写法
    • 2、基础
      • 2.1、引入
      • 2.2、第一个Vue程序
        • el挂载点
        • data数据对象
        • methods
      • Vue的生命周期(补)
      • 2.3、Vue指令
        • **Mustache: 胡子/胡须.**
        • **v-once** 不经常
        • **v-pre**
        • cloak(了解)
        • v-html
        • v-text
        • v-on绑定事件
        • v-on
          • v-on修饰符
          • v-on参数问题
        • 综合案例计数器和跑马灯
        • couputed的计算属性用法
          • 计算属性的getter和setter
          • methods和computed的比较
        • v-show
        • 数组的响应方法
        • v-if
        • v-bind
          • class属性绑定
          • style属性绑定
        • v-for
        • v-model
          • v-model修饰符
        • 过滤器filters
        • 监听属性watch
      • vue指令综合练习,todolist
      • 综合案例-购物车
      • 2.4 网络应用axios
          • 引入js库导包
          • 基本使用
        • 结合vue
        • 综合案例天气预报
        • 综合案例音乐播放器

VUE笔记-01基础

1、简介

是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

集合了react(虚拟dom)和angular(mvc)的特点

官网:https://cn.vuejs.org/

特点:

  • 解耦视图和数据
  • 可复用的组件
  • 前端路由技术
  • 状态管理
  • 虚拟DOM

基础:html+css+JavaScript技术要熟悉

mvvm

MVVMModel–view–viewmodel)是一种软件架构模式。

MVVM有助于将图形用户界面的开发与业务逻辑或后端逻辑(数据模型)的开发分离开来,这是通过置标语言或GUI代码实现的。MVVM的视图模型是一个值转换器,[1] 这意味着视图模型负责从模型中暴露(转换)数据对象,以便轻松管理和呈现对象。在这方面,视图模型比视图做得更多,并且处理大部分视图的显示逻辑。[1] 视图模型可以实现中介者模式,组织对视图所支持的用例集的后端逻辑的访问。

vue的mvvm

View层:

Ø视图层

Ø在我们前端开发中,通常就是DOM层。

Ø主要的作用是给用户展示各种信息。

Model层:

Ø数据层

Ø数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。

Ø在我们计数器的案例中,就是后面抽取出来的obj,当然,里面的数据可能没有这么简单。

VueModel层:

Ø视图模型层

Ø视图模型层是View和Model沟通的桥梁。

Ø一方面它实现了Data Binding,也就是数据绑定,将Model的改变实时的反应到View中

Ø另一方面它实现了DOM Listener,也就是DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data。

ES6补充

js高阶函数

编程范式:命令式编程、声明式编程

编程范式:面向对象编程(对象为核心)/函数式编程(函数为核心)

// 编程范式: 命令式编程/声明式编程
// 编程范式: 面向对象编程(第一公民:对象)/函数式编程(第一公民:函数)
// filter/map/reduce
// filter中的回调函数有一个要求: 必须返回一个boolean值
// true: 当返回true时, 函数内部会自动将这次回调的n加入到新的数组中
// false: 当返回false时, 函数内部会过滤掉这次的n
const nums = [10, 20, 111, 222, 444, 40, 50]// let total = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n);
// console.log(total);let total = nums.filter(function (n) {return n < 100
}).map(function (n) {return n * 2
}).reduce(function (prevValue, n) {return prevValue + n
}, 0)
console.log(total);// 1.filter函数的使用
// // 10, 20, 40, 50
// let newNums = nums.filter(function (n) {
//   return n < 100
// })
// // console.log(newNums);
//
// // 2.map函数的使用
// // 20, 40, 80, 100
// let new2Nums = newNums.map(function (n) { // 20
//   return n * 2
// })
// console.log(new2Nums);
//
// // 3.reduce函数的使用
// // reduce作用对数组中所有的内容进行汇总
// let total = new2Nums.reduce(function (preValue, n) {
//   return preValue + n
// }, 0)
// console.log(total);// 第一次: preValue 0 n 20
// 第二次: preValue 20 n 40
// 第二次: preValue 60 n 80
// 第二次: preValue 140 n 100
// 240// // 1.需求: 取出所有小于100的数字
// let newNums = []
// for (let n of nums) {
//   if (n < 100) {
//     newNums.push(n)
//   }
// }
//
// // 2.需求:将所有小于100的数字进行转化: 全部*2
// let new2Nums = []
// for (let n of newNums) {
//   new2Nums.push(n * 2)
// }
//
// console.log(new2Nums);
//
//
// // 3.需求:将所有new2Nums数字相加,得到最终的记过
// let total = 0
// for (let n of new2Nums) {
//   total += n
// }
//
// console.log(total);

let/var

事实上,var的设计是看成JavaScript是语言设计的上的错误。但是这种错误多半不能修复和移除。为了需要向后兼容。

十年前,Brendan Eich决定修复 ,于是添加了一个新的关键字,可以将let看成完美的var

  • 块级作用域

    • js中var来声明一个变量,变量的作用域只有function有概念
    • ES6中,加入了let, let它是有if和for的块级作用域.
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button><script>// ES5中的var是没有块级作用域的(if/for)// ES6中的let是由块级作用的(if/for)// ES5之前因为if和for都没有块级作用域的概念, 所以在很多时候, 我们都必须借助于function的作用域来解决应用外面变量的问题.// ES6中,加入了let, let它是有if和for的块级作用域.// 1.变量作用域: 变量在什么范围内是可用.// {//   var name = 'why';//   console.log(name);// }// console.log(name);
这样变量无论在{}里面还是外面都是可以用的,这样随意会出现问题// 2.没有块级作用域引起的问题: if的块级// var func;// if (true) {//   var name = 'why';//   func = function () {//     console.log(name);//   }//   func()// }// name = '  kobe'// func()// // console.log(name);
//这样我本来打印是why但是被修改为了kobe,这样达不到需求
{}没有作用域,但是函数有作用域,var name = 'why'function abc(bbb) { // bbb = 'why'console.log(bbb);}name = 'kobe'abc(name)  打印的还是why// 3.没有块级作用域引起的问题: for的块级,每次打印都只会打印最后一个元素吗,在点击之前for循环已经遍历到最后一个值,所以点击的时候都是最后一个。es5的解决方法,闭包。// 为什么闭包可以解决问题: 函数是一个作用域.// var btns = document.getElementsByTagName('button');// for (var i=0; i<btns.length; i++) {//   (function (num) { // 0//     btns[i].addEventListener('click', function () {//       console.log('第' + num + '个按钮被点击');//     })//   })(i)// }const btns = document.getElementsByTagName('button')for (let i = 0; i < btns.length; i++) {btns[i].addEventListener('click', function () {console.log('第' + i + '个按钮被点击');})}</script></body>
</html>

const

建议开发中只要不是变量建议优先使用const

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><script>// 1.注意一: 一旦给const修饰的标识符被赋值之后, 不能修改// const name = 'why';// name = 'abc';// 2.注意二: 在使用const定义标识符,必须进行赋值// const name;// 3.注意三: 常量的含义是指向的对象不能修改, 但是可以改变对象内部的属性.const obj = {name: 'why',age: 18,height: 1.88}// obj = {}console.log(obj);obj.name = 'kobe';obj.age = 40;obj.height = 1.87;console.log(obj);
</script></body>
</html>

增强字面量写法

函数和变量的写法:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><script>// const obj = new Object()// const obj = {//   name: 'why',//   age: 18,//   run: function () {//     console.log('在奔跑');//   },//   eat: function () {//     console.log('在次东西');//   }// }// 1.属性的增强写法const name = 'why';const age = 18;const height = 1.88// ES5的写法// const obj = {//   name: name,//   age: age,//   height: height// }// const obj = {//   name,//   age,//   height,// }//// console.log(obj);// 2.函数的增强写法// ES5的写法// const obj = {//   run: function () {////   },//   eat: function () {////   }// }const obj = {run() {},eat() {}}
</script></body>
</html>

2、基础

2.1、引入

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

开发环境版本下载:https://vuejs.org/js/vue.js

生产环境版本:https://vuejs.org/js/vue.min.js

2.2、第一个Vue程序

Vue实例的作用范围是什么呢?

Vue会管理el选项命中的元素及其内部的后代元素

是否可以使用其他的选择器?是否可以设置其他的dom元素呢?

可以使用其他的选择器,但是建议使用ID选择器可以使用其他的双标签,不能使用HTML和BODY

我们在创建Vue实例的时候,传入了一个对象options。就是new Vue({})中的{}

{}就是options,options可以传那些值:

https://cn.vuejs.org/v2/api/#%E9%80%89%E9%A1%B9-%E6%95%B0%E6%8D%AE

el挂载点

类型:string | HTMLElement

作用:决定之后Vue实例会管理哪一个DOM。

 Vue会管理el选项命中的元素及其内部的后代元素

 可以使用其他的选择器,但是建议使用ID选择器

 可以使用其他的双标签,不能使用HTML和BODY

 el是用来设置Vue实例挂载(管理)的

data数据对象

 data中可以写复杂类型的数据

 渲染复杂类型数据时,遵守js的语法即可

 Vue中用到的数据定义在data中data:数据

<div id="app">{{ message }}   </div>
// 传入的是对象vue对象中的,es6中定义变量一般用let(变量)/const(常量)
var app = new Vue({el:"#app",
data:{message:"Hello,Vue!!!",
array:[],
obj:{},
}})
        <!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>data:数据对象</title>
</head><body><div id="app">{{ message }}<h2> {{ school.name }} {{ school.mobile }}</h2><ul><li>{{ campus[0] }}</li><li>{{ campus[3] }}</li></ul></div><!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>// 编程范式:声明式编程var app = new Vue({el:"#app",data:{message:"你好 小黑!",school:{name:"新东方",mobile:"85440"},campus:["北京校区","上海校区","广州校区","深圳校区"]}})</script>// 元素js的做法(编程范式: 命令式编程)// 1.创建div元素,设置id属性// 2.定义一个变量叫message// 3.将message变量放在前面的div元素中显示// 4.修改message的数据: 今天天气不错!// 5.将修改后的数据再次替换到div元素
</body></html>

methods

类型:{ [key: string]: Function }

作用:定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用

在类里面的一般都叫方法,在文件里一般都是交函数

Vue的生命周期(补)

生命周期:一个事务从诞生到死亡的过程

开发中用的比较多的一般是created和mounted,created一般都是用于网络请求

2.3、Vue指令

如何将data中的文本数据,插入到HTML中呢?

我们已经学习过了,可以通过Mustache语法(也就是双大括号)。

Mustache: 胡子/胡须.

v-once 不经常

有时候我们可能不希望界面随意的跟随改变,这个时候,我们就可以使用一个Vue的指令

p该指令后面不需要跟任何表达式

p该指令表示元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变。

v-pre

用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法。

比如下面的代码:

p第一个h2元素中的内容会被编译解析出来对应的内容

p第二个h2元素中会直接显示{{message}}

Hello World!

{{message}}

cloak(了解)

在某些情况下,我们浏览器可能会直接显然出未编译的Mustache标签。

还没显示时屏蔽掉代码,但以后的开发都是虚拟dom,模块都会转化为函数

cloak: 斗篷

v-html

某些情况下,我们从服务器请求到的数据本身就是一个HTML代码

如果我们直接通过{{}}来输出,会将HTML代码也一起输出。

但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容。

如果我们希望解析出HTML展示

p可以使用v-html指令

Ø该指令后面往往会跟上一个string类型

Ø会将string的html解析出来并且进行渲染

v-text

可以吧数据直接关联到标签内部,只需要v-text与数据绑定即可,并且可以在内部用+号拼接字符串

缺点不够灵活会覆盖

案例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>v-text指令</title>
</head><body><div id="app"><h2 v-text="message+'!'">深圳</h2><h2 v-text="info+'!'">深圳</h2><h2>{{ message +'!'}}深圳</h2></div><!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app = new Vue({el:"#app",data:{message:"黑马程序员!!!",info:"前端与移动教研部"}})</script>
</body></html>

v-on绑定事件

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>v-on补充</title>
</head><body><div id="app"><input type="button" value="点击" v-on:click="doIt(4444,'冲啊')"><!-- 简写以@代替 --><input type="button" value="点击" @click="doIt(666,'老铁')"><input type="text" @keyup.enter="sayHi"></div><!-- 1.开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app = new Vue({el:"#app",methods: {doIt:function(p1,p2){console.log("做it");console.log(p1);console.log(p2);},sayHi:function(){alert("吃了没");}},})</script>
</body></html>

v-on

当通过methods中定义方法,以供@click调用时,需要注意参数问题

  • 情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。

但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去

  • 情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><!--1.事件调用的方法没有参数--><button @click="btn1Click()">按钮1</button><button @click="btn1Click">按钮1</button><!--2.在事件定义时, 写方法时省略了小括号, 但是方法本身是需要一个参数的, 这个时候, Vue会默认将浏览器生产的event事件对象作为参数传入到方法--><!--<button @click="btn2Click(123)">按钮2</button>--><!--<button @click="btn2Click()">按钮2</button>--><button @click="btn2Click">按钮2</button><!--3.方法定义时, 我们需要event对象, 同时又需要其他参数--><!-- 在调用方式, 如何手动的获取到浏览器参数的event对象: $event--><button @click="btn3Click(abc, $event)">按钮3</button>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊',abc: 123},methods: {btn1Click() {console.log("btn1Click");},btn2Click(event) {console.log('--------', event);},btn3Click(abc, event) {console.log('++++++++', abc, event);}}})// 如果函数需要参数,但是没有传入, 那么函数的形参为undefined// function abc(name) {//   console.log(name);// }//// abc()
</script></body>
</html>
v-on修饰符

在某些情况下,我们拿到event的目的可能是进行一些事件处理。

Vue提供了修饰符来帮助我们方便的处理一些事件:

.stop - 调用 event.stopPropagation()。

.prevent - 调用 event.preventDefault()。

.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。

.native - 监听组件根元素的原生事件。

.once - 只触发一次回调。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><!--1. .stop修饰符的使用--><div @click="divClick">aaaaaaa<button @click.stop="btnClick">按钮</button></div><!--2. .prevent修饰符的使用--><br><form action="baidu"><input type="submit" value="提交" @click.prevent="submitClick"></form><!--3. .监听某个键盘的键帽--><input type="text" @keyup.enter="keyUp"><!--4. .once修饰符的使用--><button @click.once="btn2Click">按钮2</button>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊'},methods: {btnClick() {console.log("btnClick");},divClick() {console.log("divClick");},submitClick() {console.log('submitClick');},keyUp() {console.log('keyUp');},btn2Click() {console.log('btn2Click');}}})
</script></body>
</html>
v-on参数问题

当通过methods中定义方法,以供@click调用时,需要注意参数问题

  • 情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。

    • 但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去
  • 情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。

综合案例计数器和跑马灯

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>计数器</title><style>body{background-color: #f5f5f5;
}
#app {width: 480px;height: 80px;margin: 200px auto;
}
.input-num {margin-top:20px;height: 100%;display: flex;border-radius: 10px;overflow: hidden;box-shadow: 4px 4px 4px #adadad;border: 1px solid #c7c7c7;background-color: #c7c7c7;
}
.input-num button {width: 150px;height: 100%;font-size: 40px;color: #ad2a27;cursor: pointer;border: none;outline: none;background-color:rgba(0, 0, 0, 0);
}
.input-num span {height: 100%;font-size: 40px;flex: 1;text-align: center;line-height: 80px;font-family:auto;background-color: white;
}
img{float: right;margin-top: 50px;
}</style></head><body><div id="app"><!-- 计数器 --><div class="input-num"><button @click="sub">-</button><span>{{ num }}</span><button @click="add">+</button></div></div></body>
</html>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 编码 -->
<script>// 创建Vue实例var app = new Vue({el: "#app",data: {num: 1,min: 0,max: 10},methods: {sub() {if (this.num > this.min) {this.num--;} else {alert("别点啦,到底啦");}},add() {if (this.num < this.max) {this.num++;} else {alert("别点啦,到头啦");}}}});
</script>

跑马灯

<!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"><button @click="run()">浪起来</button><button @click="stop()">低调</button><p>{{msg}}</p></div><script src="vue.js"></script><script>var vm = new Vue({el: "#app",data: {msg: "今天是个好日子!",timer:null},methods: {run: function () {timer = window.setInterval(function () {vm.msg = vm.msg.substr(1) + vm.msg.substr(0, 1);}, 100);},stop: function () {window.clearInterval(timer);}}})</script>
</body></html>

couputed的计算属性用法

计算属性相对于普通的方法,在计算方面有缓存,效率更高

我们知道,在模板中可以直接通过插值语法显示一些data中的数据。

但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示

比如我们有firstName和last Name两个变量,我们需要显示完整的名称。

但是如果多个地方都需要显示完整的名称,我们就需要写多个{{firstName}} {{last Name}}

我们可以将上面的代码换成计算属性:

我们发现计算属性是写在实例的computed选项中的

-------------------------------
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><h2>{{firstName + ' ' + lastName}}</h2><h2>{{firstName}} {{lastName}}</h2><h2>{{getFullName()}}</h2><h2>{{fullName}}</h2>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {firstName: 'Lebron',lastName: 'James'},// computed: 计算属性(),起名字最好是用属性名computed: {fullName: function () {return this.firstName + ' ' + this.lastName}},methods: {getFullName() {return this.firstName + ' ' + this.lastName}}})
</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"><p>总价格:{{totalPrice}}</p><p>单价:{{price}}</p><p>数量:{{num}}</p><div><button v-on:click="num==0?0:num--">减少数量</button><button @click ="num++">增加数量</button></div></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var vm = new Vue({el:"#app",data:{price:20,num:0},computed:{//总价格totalPricetotalPrice(){return this.price*this.num}}})</script>
</body>
</html>
--------------------------
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><h2>总价格: {{totalPrice}}</h2>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {books: [{id: 110, name: 'Unix编程艺术', price: 119},{id: 111, name: '代码大全', price: 105},{id: 112, name: '深入理解计算机原理', price: 98},{id: 113, name: '现代操作系统', price: 87},]},computed: {totalPrice: function () {let result = 0for (let i=0; i < this.books.length; i++) {result += this.books[i].price}return result// for (let i in this.books) {//   this.books[i]// }//// for (let book of this.books) {//// }}}})
</script></body>
</html>
计算属性的getter和setter

本质上是个属性,只是把set和get省略了,本质上覆盖了get,所以调用的时候并不用加()

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><h2>{{fullName}}</h2>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {firstName: 'Kobe',lastName: 'Bryant'},computed: {// fullName: function () {  //   return this.firstName + ' ' + this.lastName// }// name: 'coderwhy'// 计算属性一般是没有set方法, 只读属性.fullName: {set: function(newValue) {// console.log('-----', 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>
</html>
methods和computed的比较

methods每次都会调用。computed只会调用一次。效率更高

v-show

v-if和v-show都可以决定一个元素是否渲染,那么开发中我们如何选择呢?

  • v-if当条件为false时,压根不会有对应的元素在DOM中。

  • v-show当条件为false时,仅仅是将元素的display属性设置为none而已。

开发中如何选择呢?

  • 当需要在显示与隐藏之间切片很频繁时,使用v-show

  • 当只有一次切换时,通过使用v-if

根据表达式的真假,切换元素的显示和隐藏

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>v-show指令</title></head><body><div id="app"><input type="button" value="切换显示状态" @click="changeIsShow"><input type="button" value="累加年龄" @click="addAge"><img v-show="isShow" src="./img/monkey.gif" alt=""><img v-show="age>=18" src="./img/monkey.gif" alt=""></div><!-- 1.开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app = new Vue({el:"#app",data:{isShow:false,age:17},methods: {changeIsShow:function(){this.isShow = !this.isShow;},addAge:function(){this.age++;}},})</script></body>
</html>

数组的响应方法

因为Vue是响应式的,所以当数据发生变化时,Vue会自动检测数据变化,视图会发生对应的更新。

Vue中包含了一组观察数组编译的方法,使用它们改变数组也会触发视图的更新。

通过索引值来修改元素的值不是响应式的

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><ul><li v-for="item in letters">{{item}}</li></ul><button @click="btnClick">按钮</button>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {letters: ['a', 'b', 'c', 'd']},methods: {btnClick() {// 1.push方法// this.letters.push('aaa')// this.letters.push('aaaa', 'bbbb', 'cccc')// 2.pop(): 删除数组中的最后一个元素// this.letters.pop();// 3.shift(): 删除数组中的第一个元素// this.letters.shift();// 4.unshift(): 在数组最前面添加元素// this.letters.unshift()// this.letters.unshift('aaa', 'bbb', 'ccc')// 5.splice作用: 删除元素/插入元素/替换元素// 删除元素: 第二个参数传入你要删除几个元素(如果没有传,就删除后面所有的元素)// 替换元素: 第二个参数, 表示我们要替换几个元素, 后面是用于替换前面的元素// 插入元素: 第二个参数, 传入0, 并且后面跟上要插入的元素// splice(start)// splice(start):this.letters.splice(1, 3, 'm', 'n', 'l', 'x')// this.letters.splice(1, 0, 'x', 'y', 'z')// 5.sort()// this.letters.sort()// 6.reverse()// this.letters.reverse()// 注意: 通过索引值修改数组中的元素// this.letters[0] = 'bbbbbb';// this.letters.splice(0, 1, 'bbbbbb')// set(要修改的对象, 索引值, 修改后的值)// Vue.set(this.letters, 0, 'bbbbbb')}}})// function sum(num1, num2) {//   return num1 + num2// }//// function sum(num1, num2, num3) {//   return num1 + num2 + num3// }// function sum(...num) {//   console.log(num);// }//// sum(20, 30, 40, 50, 601, 111, 122, 33)</script></body>
</html>

v-if

判断语句 v-else指令,v-else-if基本相同

•v-show的元素一直存在于页面中,只是控制显示与隐藏。V-if为真的时元素在页面中,否则不在页面中。

•如果元素需要频繁切换,用v-show较好。如果运行条件很少改变,用v-if较好。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>v-if指令</title>
</head>
<body><div id="app"><input type="button" value="切换显示" @click="toggleIsShow"><p v-if="isShow">黑马程序员</p><p v-show="isShow">黑马程序员 - v-show修饰<p v-text="'温度:'+temperature"></p><button @click="add">+</button></p><h2 v-if="temperature>=30" >热死啦</h2></div><!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app = new Vue({el:"#app",data:{isShow:false,temperature:20},methods: {toggleIsShow:function(){this.isShow = !this.isShow;},add:function(){this.temperature++;}},})</script>
</body></html>

v-bind

设置元素的属性如src,title,class,style

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>v-bind指令</title><style>.active{border: 1px solid red;}</style>
</head><body><div id="app"><img v-bind:src="imgSrc" alt=""><br><img :src="imgSrc" alt="" :title="imgTitle+'!!!'" :class="isActive?'active':''" @click="toggleActive"><br><img :src="imgSrc" alt="" :title="imgTitle+'!!!'" :class="{active:isActive}" @click="toggleActive"></div><!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app = new Vue({el:"#app",data:{imgSrc:"http://www.itheima.com/images/logo.png",imgTitle:"黑马程序员",isActive:false},methods: {toggleActive:function(){this.isActive = !this.isActive;}},})</script>
</body></html>
class属性绑定

若样式多,可以用数组或队形的形式绑定区别就是[]和{}

案例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>.active {color: red;}</style>
</head>
<body><div id="app"><!--<h2 class="active">{{message}}</h2>--><!--<h2 :class="active">{{message}}</h2>--><!--<h2 v-bind:class="{key1: value1, key2: value2}">{{message}}</h2>--><!--<h2 v-bind:class="{类名1: true, 类名2: boolean}">{{message}}</h2>--><h2 class="title" v-bind:class="{active: isActive, line: isLine}">{{message}}</h2><h2 class="title" v-bind:class="getClasses()">{{message}}</h2><button v-on:click="btnClick">按钮</button>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊',isActive: true,isLine: true},methods: {btnClick: function () {this.isActive = !this.isActive},getClasses: function () {return {active: this.isActive, line: this.isLine}}}})
</script></body>
</html></script>--------非内连绑定--------<div id="box"><div class="default" v-bind:class="classObject">Vue.js样式绑定</div>
</div>
<script type="text/javascript">var vm = new Vue({el : '#box',data : {classObject : {size : true,color : true}}});
</script>
--------------计算属性对象绑定--------<div id="box"><div class="default" v-bind:class="show">Vue.js样式绑定</div>
</div>
<script type="text/javascript">var vm = new Vue({el : '#box',data : { isSize : true, isColor : true },computed : {show : function(){return {size : this.isSize,color : this.isColor}}}});
</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><style>.a{color: red;font-style: italic;}</style></head><body><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><div id="app"><h1 v-bind:class="[isShow?'a':'']">{{message}}</h1><button @click="isShow=!isShow">添加样式</button></div><script>var vm=new Vue({el:'#app',data:{message:"Vue.js样式绑定",isShow:true }})</script></body></html>
style属性绑定

----------内连绑定---------------
<div id="box">fontWeight是类名<div v-bind:style="{fontWeight : weight, 'font-size' : fontSize + 'px'}">Vue.js样式绑定</div>
</div>
<script type="text/javascript">var vm = new Vue({el : '#box',data : {weight : 'bold',fontSize : 30}});
</script>
--------非内连绑定------------
<div id="box"><div v-bind:style="styleObject">Vue.js样式绑定</div>
</div>
<script type="text/javascript">var vm = new Vue({el : '#box',data : {styleObject : {fontWeight : 'bold','font-size' : '30px'}}});
</script>
---------计算属性绑定----
<div id="box"><div v-bind:style="show">Vue.js样式绑定</div>
</div>
<script type="text/javascript">var vm = new Vue({el : '#box',data : {weight : 'bold',fontSize : 30},computed : {show : function(){return {fontWeight : this.weight,'font-size' : this.fontSize + 'px'}}}});
</script>
---------数组语法--------
<div id="box"><div v-bind:style="[size,weight,decoration]">Vue.js样式绑定</div>
</div>
<script type="text/javascript">var vm = new Vue({el : '#box',data : {size : {fontSize : '24px'},weight : {'font-weight' : 'bold'},decoration : {'text-decoration' : 'underline'}}});
</script>

v-for

需要记住v-for遍历对象时的遍历的默认是value要遍历key指定即可

官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性。

key不能乱指定,要指定 一一对应关系的

为什么需要这个key属性呢(了解)?

这个其实和Vue的虚拟DOM的Diff算法有关系。

当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点

  • 我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的。

​ 即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

​ 所以我们需要使用key来给每个节点做一个唯一标识

  • Diff算法就可以正确的识别此节点

找到正确的位置区插入新的节点。

<div id="app"><ul><li v-for="item in letters" :key="item">{{item}}</li></ul>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {letters: ['A', 'B', 'C', 'D', 'E']}})
</script>

所以一句话,key的作用主要是为了高效的更新虚拟DOM**。**

<!DOCTYPE html>
<html lang="en">
遍历数组一般都是一个一个取出
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>v-for指令</title>
</head><body><div id="app"><input type="button" value="添加数据" @click="add"><input type="button" value="移除数据" @click="remove"><ul><li v-for="(it,index) in arr">{{ index+1 }}黑马程序员校区:{{ it }}</li></ul><h2 v-for="item in vegetables" v-bind:title="item.name">{{ item.name }}</h2></div><!-- 1.开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app = new Vue({el:"#app",data:{arr:["北京","上海","广州","深圳"],vegetables:[{name:"西兰花炒蛋"},{name:"蛋炒西蓝花"}]},methods: {add:function(){this.vegetables.push({ name:"花菜炒蛋" });},remove:function(){this.vegetables.shift();}},})</script>
</body></html>----------------------案例2--------------------
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><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>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {names: ['why', 'kobe', 'james', 'curry']}})
</script></body>
</html>
---------------------------------------------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><!--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><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {info: {name: 'why',age: 18,height: 1.88}}})
</script></body>
</html>

v-model

表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。

Vue中使用v-model指令来实现表单元素和数据的双向绑定。

原理

nv-model其实是一个语法糖,它的背后本质上是包含两个操作:

  • 1.v-bind绑定一个value属性

  • 2.v-on指令给当前元素绑定input事件

    也就是说下面的代码:等同于下面的代码:

    <input type="text" v-model="message">
    等同于
    <input type="text" v-bind:value="message" v-on:input="message = $event.target.value">

双向绑定数据

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>v-model指令</title>
</head><body><div id="app"><input type="button" value="修改message" @click="setM"><input type="text" v-model="message" @keyup.enter="getM"><h2>{{ message }}</h2></div><!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app = new Vue({el:"#app",data:{message:"黑马程序员"},methods: {getM:function(){alert(this.message);},setM:function(){this.message ="酷丁鱼";}},})</script>
</body></html>

结合radio使用

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><label for="male"><input type="radio" id="male" value="男" v-model="sex">男</label><label for="female"><input type="radio" id="female" value="女" v-model="sex">女</label><h2>您选择的性别是: {{sex}}</h2>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊',sex: '女'}})
</script></body>
</html>

结合checkbox使用

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><!--1.checkbox单选框--><!--<label for="agree">--><!--<input type="checkbox" id="agree" v-model="isAgree">同意协议--><!--</label>--><!--<h2>您选择的是: {{isAgree}}</h2>--><!--<button :disabled="!isAgree">下一步</button>--><!--2.checkbox多选框--><input type="checkbox" value="篮球" v-model="hobbies">篮球<input type="checkbox" value="足球" v-model="hobbies">足球<input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球<input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球<h2>您的爱好是: {{hobbies}}</h2><label v-for="item in originHobbies" :for="item"><input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}</label>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊',isAgree: false, // 单选框hobbies: [], // 多选框,originHobbies: ['篮球', '足球', '乒乓球', '羽毛球', '台球', '高尔夫球']}})
</script></body>
</html>

结合select

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><!--1.选择一个--><select name="abc" v-model="fruit"><option value="苹果">苹果</option><option value="香蕉">香蕉</option><option value="榴莲">榴莲</option><option value="葡萄">葡萄</option></select><h2>您选择的水果是: {{fruit}}</h2><!--2.选择多个--><select name="abc" v-model="fruits" multiple><option value="苹果">苹果</option><option value="香蕉">香蕉</option><option value="榴莲">榴莲</option><option value="葡萄">葡萄</option></select><h2>您选择的水果是: {{fruits}}</h2>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊',fruit: '香蕉',fruits: []}})
</script></body>
</html>
v-model修饰符
  • lazy修饰符:

    • 默认情况下,v-model默认是在input事件中同步输入框的数据的。
    • 也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。
    • lazy修饰符可以让数据在失去焦点或者回车时才会更新:
  • number修饰符:

    • 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。
    • 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。
    • number修饰符可以让在输入框中输入的内容自动转成数字类型:
  • trim修饰符:

    • 如果输入的内容首尾有很多空格,通常我们希望将其去除
    • trim修饰符可以过滤内容左右两边的空格
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><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>{{age}}-{{typeof age}}</h2><!--3.修饰符: trim--><input type="text" v-model.trim="name"><h2>您输入的名字:{{name}}</h2>
</div><script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊',age: 0,name: ''}})var age = 0age = '1111'age = '222'
</script></body>
</html>

过滤器filters

•过滤器这种成员的作用是:类似方法形式,对数据进行处理,返回处理后的结果。在管道符“|”后面使用。

•使用场景:差值表达式中使用过滤器、v-bind属性绑定中使用过滤器

<div id="box"><span>{{str | lowercase | firstUppercase}}</span>
</div>
<script type="text/javascript">var demo = new Vue({el : '#box',data : {str : 'HTML+CSS+JavaScript'},filters : {lowercase : function(value){return value.toLowerCase();},firstUppercase : function(value){return value.charAt(0).toUpperCase()+value.substr(1);}}});
</script>
--------------------------------------------------------------------------------------------------------
<div id="box"><span>{{price | formatPrice("¥")}}</span>
</div>
<script type="text/javascript">var demo = new Vue({el : '#box',data : {price : 199},filters : {formatPrice : function(value,symbol){return symbol + value.toFixed(2);}}});
</script>

监听属性watch

监听属性是Vue.js提供的一种用来监听和响应Vue实例中的数据变化的方式。

监听属性可以用以下两种情况定义

<script type="text/javascript">var vm = new Vue({el:'#example',data:{fullname : '韦小宝'},watch : {fullname : function(newValue,oldValue){alert("原值:"+oldValue+" 新值:"+newValue);}}})vm.fullname = '宋小宝';
</script>
--------------------------------------------------------------------
<script type="text/javascript">var vm = new Vue({el:'#example',data:{fullname : '韦小宝'}})vm.$watch('fullname',function(newValue,oldValue){alert("原值:"+oldValue+" 新值:"+newValue);});vm.fullname = '宋小宝';
</script>

案例:

<!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><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><div id="app">¥<input type="text" v-model="rmb"><br>$ <input type="text"v-model="dollar"><br>{{rmb|toRevert}}人民币 = {{dollar|toRevert}}美元</div><script>var app = new Vue({el:"#app",data:{rate:6.8,rmb:0,dollar:0},watch:{rmb:function(val){this.dollar = val/this.rate;},dollar:function(val){this.rmb = val*this.rate;}}, filters:{toRevert:function(value){//保留两位小数return value.toFixed(2);}} })</script>
</body>
</html>

vue指令综合练习,todolist

<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" /><title>小黑记事本</title><meta http-equiv="content-type" content="text/html; charset=UTF-8" /><meta name="robots" content="noindex, nofollow" /><meta name="googlebot" content="noindex, nofollow" /><meta name="viewport" content="width=device-width, initial-scale=1" /><link rel="stylesheet" type="text/css" href="./css/index.css" />
</head><body><!-- 主体区域 --><section id="todoapp"><!-- 输入框 --><header class="header"><h1>小黑记事本</h1><input v-model="inputValue" @keyup.enter="add" autofocus="autofocus" autocomplete="off" placeholder="请输入任务"class="new-todo" /></header><!-- 列表区域 --><section class="main"><ul class="todo-list"><li class="todo" v-for="(item,index) in list"><div class="view"><span class="index">{{ index+1 }}.</span><label>{{ item }}</label><button class="destroy" @click="remove(index)"></button></div></li></ul></section><!-- 统计和清空 --><footer class="footer" v-show="list.length!=0"><span class="todo-count" v-if="list.length!=0"><strong>{{ list.length }}</strong> items left</span><button v-show="list.length!=0" class="clear-completed" @click="clear">Clear</button></footer></section><!-- 底部 --><footer class="info"><p><!-- <a href="http://www.itheima.com/"><img src="./img/black.png" alt="" /></a> --></p></footer><!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>var app = new Vue({el: "#todoapp",data: {list: ["写代码", "吃饭饭", "睡觉觉"],inputValue: "好好学习,天天向上"},methods: {add: function () {this.list.push(this.inputValue);},remove: function (index) {console.log("删除");console.log(index);this.list.splice(index, 1);},clear: function () {this.list = [];}},})</script>
</body></html>
html,
body {margin: 0;padding: 0;
}
body {background: #fff;
}
button {margin: 0;padding: 0;border: 0;background: none;font-size: 100%;vertical-align: baseline;font-family: inherit;font-weight: inherit;color: inherit;-webkit-appearance: none;appearance: none;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;
}body {font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;line-height: 1.4em;background: #f5f5f5;color: #4d4d4d;min-width: 230px;max-width: 550px;margin: 0 auto;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;font-weight: 300;
}:focus {outline: 0;
}.hidden {display: none;
}#todoapp {background: #fff;margin: 180px 0 40px 0;position: relative;box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}#todoapp input::-webkit-input-placeholder {font-style: italic;font-weight: 300;color: #e6e6e6;
}#todoapp input::-moz-placeholder {font-style: italic;font-weight: 300;color: #e6e6e6;
}#todoapp input::input-placeholder {font-style: italic;font-weight: 300;color: gray;
}#todoapp h1 {position: absolute;top: -160px;width: 100%;font-size: 60px;font-weight: 100;text-align: center;color: rgba(175, 47, 47, .8);-webkit-text-rendering: optimizeLegibility;-moz-text-rendering: optimizeLegibility;text-rendering: optimizeLegibility;
}.new-todo,
.edit {position: relative;margin: 0;width: 100%;font-size: 24px;font-family: inherit;font-weight: inherit;line-height: 1.4em;border: 0;color: inherit;padding: 6px;border: 1px solid #999;box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);box-sizing: border-box;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;
}.new-todo {padding: 16px;border: none;background: rgba(0, 0, 0, 0.003);box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
}.main {position: relative;z-index: 2;border-top: 1px solid #e6e6e6;
}.toggle-all {width: 1px;height: 1px;border: none; /* Mobile Safari */opacity: 0;position: absolute;right: 100%;bottom: 100%;
}.toggle-all + label {width: 60px;height: 34px;font-size: 0;position: absolute;top: -52px;left: -13px;-webkit-transform: rotate(90deg);transform: rotate(90deg);
}.toggle-all + label:before {content: "❯";font-size: 22px;color: #e6e6e6;padding: 10px 27px 10px 27px;
}.toggle-all:checked + label:before {color: #737373;
}.todo-list {margin: 0;padding: 0;list-style: none;max-height: 420px;overflow: auto;
}.todo-list li {position: relative;font-size: 24px;border-bottom: 1px solid #ededed;height: 60px;box-sizing: border-box;
}.todo-list li:last-child {border-bottom: none;
}.todo-list .view .index {position: absolute;color: gray;left: 10px;top: 20px;font-size: 16px;
}.todo-list li .toggle {text-align: center;width: 40px;/* auto, since non-WebKit browsers doesn't support input styling */height: auto;position: absolute;top: 0;bottom: 0;margin: auto 0;border: none; /* Mobile Safari */-webkit-appearance: none;appearance: none;
}.todo-list li .toggle {opacity: 0;
}.todo-list li .toggle + label {/*Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/*/background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E");background-repeat: no-repeat;background-position: center left;
}.todo-list li .toggle:checked + label {background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E");
}.todo-list li label {word-break: break-all;padding: 15px 15px 15px 60px;display: block;line-height: 1.2;transition: color 0.4s;
}.todo-list li.completed label {color: #d9d9d9;text-decoration: line-through;
}.todo-list li .destroy {display: none;position: absolute;top: 0;right: 10px;bottom: 0;width: 40px;height: 40px;margin: auto 0;font-size: 30px;color: #cc9a9a;margin-bottom: 11px;transition: color 0.2s ease-out;
}.todo-list li .destroy:hover {color: #af5b5e;
}.todo-list li .destroy:after {content: "×";
}.todo-list li:hover .destroy {display: block;
}.todo-list li .edit {display: none;
}.todo-list li.editing:last-child {margin-bottom: -1px;
}.footer {color: #777;padding: 10px 15px;height: 20px;text-align: center;border-top: 1px solid #e6e6e6;
}.footer:before {content: "";position: absolute;right: 0;bottom: 0;left: 0;height: 50px;overflow: hidden;box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6,0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6,0 17px 2px -6px rgba(0, 0, 0, 0.2);
}.todo-count {float: left;text-align: left;
}.todo-count strong {font-weight: 300;
}.filters {margin: 0;padding: 0;list-style: none;position: absolute;right: 0;left: 0;
}.filters li {display: inline;
}.filters li a {color: inherit;margin: 3px;padding: 3px 7px;text-decoration: none;border: 1px solid transparent;border-radius: 3px;
}.filters li a:hover {border-color: rgba(175, 47, 47, 0.1);
}.filters li a.selected {border-color: rgba(175, 47, 47, 0.2);
}.clear-completed,
html .clear-completed:active {float: right;position: relative;line-height: 20px;text-decoration: none;cursor: pointer;
}.clear-completed:hover {text-decoration: underline;
}.info {margin: 50px auto 0;color: #bfbfbf;font-size: 15px;text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);text-align: center;
}.info p {line-height: 1;
}.info a {color: inherit;text-decoration: none;font-weight: 400;
}.info a:hover {text-decoration: underline;
}/*Hack to remove background from Mobile Safari.Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio: 0) {.toggle-all,.todo-list li .toggle {background: none;}.todo-list li .toggle {height: 40px;}
}@media (max-width: 430px) {.footer {height: 50px;}.filters {bottom: 10px;}
}

综合案例-购物车

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="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="removeHandle(index)">移除</button></td></tr></tbody></table><h2>总价格: {{totalPrice | showPrice}}</h2></div><h2 v-else>购物车为空</h2>
</div><script src="../js/vue.js"></script>
<script src="main.js"></script>
<script>
</script>
</body>
</html>
table {border: 1px solid #e9e9e9;border-collapse: collapse;border-spacing: 0;
}th, td {padding: 8px 16px;border: 1px solid #e9e9e9;text-align: left;
}th {background-color: #f7f7f7;color: #5c6b77;font-weight: 600;
}
const app = new Vue({el: '#app',data: {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: {// getFinalPrice(price) {//   return '¥' + price.toFixed(2)// }increment(index) {this.books[index].count++},decrement(index) {this.books[index].count--},removeHandle(index) {this.books.splice(index, 1)}},computed: {totalPrice() {// 1.普通的for循环// let totalPrice = 0// for (let i = 0; i < this.books.length; i++) {//   totalPrice += this.books[i].price * this.books[i].count// }// return totalPrice// 2.for (let i in this.books)// let totalPrice = 0// for (let i in this.books) {//   const book = this.books[i]//   totalPrice += book.price * book.count// }//// return totalPrice// 3.for (let i of this.books)// let totalPrice = 0// for (let item of this.books) {//   totalPrice += item.price * item.count// }// return totalPricereturn this.books.reduce(function (preValue, book) {return preValue + book.price * book.count}, 0)}},filters: {showPrice(price) {return '¥' + price.toFixed(2)}}
})

2.4 网络应用axios

axios封装了ajax只有请求功能,体量小,与vue框架结合非常方便。

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

引入js库导包

联网cdn:<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

本地官网下载即可

get方式可以查询本地或网络数据

post访问方式,可以改变本地或网络数据

推荐接口

•天行数据:https://www.tianapi.com/

网易云API:https://autumnfish.cn/

基本使用
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>axios基本使用</title>
</head><body><input type="button" value="get请求" class="get"><input type="button" value="post请求" class="post"><!-- 官网提供的 axios 在线地址 --><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script>/*接口1:随机笑话请求地址:https://autumnfish.cn/api/joke/list请求方法:get请求参数:num(笑话条数,数字)响应内容:随机笑话*/document.querySelector(".get").onclick = function () {axios.get("https://autumnfish.cn/api/joke/list?num=6")// axios.get("https://autumnfish.cn/api/joke/list1234?num=6").then(function (response) {console.log(response);},function(err){console.log(err);})}/*接口2:用户注册请求地址:https://autumnfish.cn/api/user/reg请求方法:post请求参数:username(用户名,字符串)响应内容:注册成功或失败*/document.querySelector(".post").onclick = function () {axios.post("https://autumnfish.cn/api/user/reg",{username:"盐焗西兰花"}).then(function(response){console.log(response);console.log(this.skill);},function (err) {console.log(err);})}</script>
</body></html>

结合vue

get

<!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"><button @click="chaxun">点击</button><ol type="1"><li v-for="item in lists">{{item}}</li></ol></div><script src="vue.js"></script><script src="axios.min.js"></script><script>new Vue({el: "#app",data: {lists: []},methods: {chaxun: function () {axios.get("https://autumnfish.cn/api/joke/list?num=3").then(response => {console.log(response)this.lists = response.data.jokes}, err => {});}}});</script>
</body></html>

post

<!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"><p>用户名:<input type="text" v-model="msg"></p><button @click="register">注册</button></div><script src="vue.js"></script><script src="axios.min.js"></script><script>new Vue({   el: "#app",data: {msg: ''},methods: {register: function () {axios.post("https://autumnfish.cn/api/user/reg", { username: this.msg }).then(response => {alert(response.data)}, err => {console.log(err)})}}})</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><style>button{background-color: #1dc9f4;text-align: center;color: #d0f4fc;}input{width: 800px;height: 30px;}.box1{margin-left: 500px;}ul {display: flex;}li {list-style: none;flex: 1;text-align: center;border-right: 1px solid #ccc;height: 300px}li:last-child {border-right: none;}li:first-child {background-color: lightyellow;}h2 {color: orange;height: 40px}li p:nth-child(2) {color: orange;height: 40px}</style>
</head>
<body><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><div id="app"><h2 style="color:#36cdf4;" align="center">天气查询</h2><div class="box1"><input type="text" placeholder="输入城市" v-model="city"  @keyup.enter="search"><button style="height: 40px;width: 60px;"@click="search">查询</button>  </div><p align="center"><span @click="select('北京')">北京</span> <span @click="select('上海')">上海</span><span @click="select('广州')">广州</span> <span @click="select('深圳')">深圳</span><span @click="select('郑州')">郑州</span> <span @click="select('武汉')">武汉</span></p><h2 style="color: red;" v-model="city">{{city}}</h2><ul><li v-for=" item in weathers"><h2>{{item.weather}}</h2><p>{{item.lowest}}~{{item.highest}}</p><p>{{item.date}} {{item.week}}</p><p>{{item.tips}}</p></li></ul></div><script>var app = new Vue({el:"#app",data:{city:"南京",weathers:[]},methods:{search:function(){if (this.city != "") {axios.get("http://api.tianapi.com/txapi/tianqi/index?key=f1038a07de3b76e998e22d422dd4fc1a&city="+this.city+"市").then(response=>{this.weathers = response.data.newslist;},err => {alert(err)})}},select:function(value){this.city = value;this.search();},},mounted: function () {this.search();}})</script>
</body>
</html>

综合案例音乐播放器

源码下载:https://gitee.com/xiaoqiang001/vue_material

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>悦听player</title><!-- 样式 --><link rel="stylesheet" href="./css/index.css">
</head><body><div class="wrap"><!-- 播放器主体区域 --><div class="play_wrap" id="player"><div class="search_bar"><img src="data:images/player_title.png" alt="" /><!-- 搜索歌曲 --><input type="text" autocomplete="off" v-model="query" @keyup.enter="searchMusic" /></div><div class="center_con"><!-- 搜索歌曲列表 --><div class='song_wrapper'><ul class="song_list"><li v-for="item in musicList"><a href="javascript:;" @click="playMusic(item.id)"></a> <b>{{ item.name }}</b> <span v-if="item.mvid!=0" @click="playMV(item.mvid)"><i></i></span></li></ul><img src="data:images/line.png" class="switch_btn" alt=""></div><!-- 歌曲信息容器 --><div class="player_con" :class="{playing:isPlaying}"><img src="data:images/player_bar.png" class="play_bar" /><!-- 黑胶碟片 --><img src="data:images/disc.png" class="disc autoRotate" /><img :src="musicCover" class="cover autoRotate" /></div><!-- 评论容器 --><div class="comment_wrapper"><h5 class='title'>热门留言</h5><div class='comment_list'><dl v-for="item in hotComments"><dt><img :src="item.user.avatarUrl" alt=""></dt><dd class="name">{{ item.nickname}}</dd><dd class="detail">{{ item.content }}</dd></dl></div><img src="data:images/line.png" class="right_line"></div></div><div class="audio_con"><audio ref='audio' @play="play" @pause="pause" :src="musicUrl" controls autoplay loop class="myaudio"></audio></div><div class="video_con" v-show="isShow" style="display: none;"><video :src="mvUrl" controls="controls"></video><div class="mask" @click="hide"></div></div></div></div><!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- 官网提供的 axios 在线地址 --><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script src="./js/main.js"></script>
</body></html>

vue

/*1:歌曲搜索接口请求地址:https://autumnfish.cn/search请求方法:get请求参数:keywords(查询关键字)响应内容:歌曲搜索结果2:歌曲url获取接口请求地址:https://autumnfish.cn/song/url请求方法:get请求参数:id(歌曲id)响应内容:歌曲url地址3.歌曲详情获取请求地址:https://autumnfish.cn/song/detail请求方法:get请求参数:ids(歌曲id)响应内容:歌曲详情(包括封面信息)4.热门评论获取请求地址:https://autumnfish.cn/comment/hot?type=0请求方法:get请求参数:id(歌曲id,地址中的type固定为0)响应内容:歌曲的热门评论5.mv地址获取请求地址:https://autumnfish.cn/mv/url请求方法:get请求参数:id(mvid,为0表示没有mv)响应内容:mv的地址
*/
var app = new Vue({el: "#player",data: {// 查询关键字query: "",// 歌曲数组musicList: [],// 歌曲地址musicUrl: "",// 歌曲封面musicCover: "",// 歌曲评论hotComments: [],// 动画播放状态isPlaying: false,// 遮罩层的显示状态isShow: false,// mv地址mvUrl: ""},methods: {// 歌曲搜索searchMusic: function() {var that = this;axios.get("https://autumnfish.cn/search?keywords=" + this.query).then(function(response) {// console.log(response);that.musicList = response.data.result.songs;console.log(response.data.result.songs);},function(err) {});},// 歌曲播放playMusic: function(musicId) {//   console.log(musicId);var that = this;// 获取歌曲地址axios.get("https://autumnfish.cn/song/url?id=" + musicId).then(function(response) {// console.log(response);// console.log(response.data.data[0].url);that.musicUrl = response.data.data[0].url;},function(err) {});// 歌曲详情获取axios.get("https://autumnfish.cn/song/detail?ids=" + musicId).then(function(response) {// console.log(response);// console.log(response.data.songs[0].al.picUrl);that.musicCover = response.data.songs[0].al.picUrl;},function(err) {});// 歌曲评论获取axios.get("https://autumnfish.cn/comment/hot?type=0&id=" + musicId).then(function(response) {// console.log(response);// console.log(response.data.hotComments);that.hotComments = response.data.hotComments;},function(err) {});},// 歌曲播放play: function() {// console.log("play");this.isPlaying = true;},// 歌曲暂停pause: function() {// console.log("pause");this.isPlaying = false;},// 播放mvplayMV: function(mvid) {var that = this;axios.get("https://autumnfish.cn/mv/url?id=" + mvid).then(function(response) {// console.log(response);console.log(response.data.data.url);that.isShow = true;that.mvUrl = response.data.data.url;},function(err) {});},// 隐藏hide: function() {this.isShow = false;}}
});

Vue学习笔记01-基础部分相关推荐

  1. Vue学习笔记01——Vue开发基础

    一.Vue实例配置选项 选项 说明 data Vue实例数据对象 methods 定义Vue中的方法 components 定义子组件 computed 计算属性 filters 过滤器 el 唯一根 ...

  2. 图神经网络学习笔记-01基础

    图神经网络-01基础-图与图学习 文章目录 图神经网络-01基础-图与图学习 图是什么 图的定义 图的基本表示方法 e.g 图的存储 图的类型和性质 图算法 1. 寻路和图搜索算法 1). 搜索算法 ...

  3. 【狂神说Java】Vue学习笔记01:前端知识体系

    本文根据B站[狂神说Java]vue系列视频整理,如需观看视频,请点击链接跳转 [狂神说Java]Vue视频 2.前端知识体系 想要成为真正的"互联网Java全栈工程师"还有很长的 ...

  4. Vue学习笔记01:准备开发与调试环境

    文章目录 一.安装Vue.js (一)使用独立版本 1.开发版本 2.生产版本 3.案例演示 (二)使用CDN方式 1.采用 Staticfile CDN 2.案例演示 (三)使用NPM方式 1.安装 ...

  5. PHP学习笔记01——基础语法

    1 <!DOCTYPE html> 2 <html> 3 <?php 4 // 1.使用$加变量名来表示变量,php是弱类型语言,不要求在使用变量前声明,第一次赋值时变量 ...

  6. python基础知识笔记简书_Python学习笔记01——基础知识

    Python常用数据类型: 整数(int),浮点数(float),字符串(str) 布尔型(True,False),空值(None) 列表(list):一种有序集合,可以随时添加删除其中的元素. cl ...

  7. 黑马Android76期学习笔记01基础--day07--广播,有、无序广播、特殊广播接受者、样式和主题,this与context的区别、普通对话框,进度条对话框、帧动画

    1.广播Broadcastreceiver 1.定义一个广播接收者(定义一个类并继承BroadcastReceiver) public class OutGoingCallReveiver exten ...

  8. Vue学习笔记02——Vue路由

    Vue学习笔记01--Vue开发基础 一.初识路由 1.路由的作用 Vue的路由是前端路由,可以让组件之间互相切换. 2.vue-router.js文件 Vue的路由使用需要引入vue-router. ...

  9. XML学习笔记01【xml_基础、xml_约束】

    Java后端 学习路线 笔记汇总表[黑马程序员] XML学习笔记01[xml_基础.xml_约束][day01] XML学习笔记02[xml_解析][day01] 目录 01 xml_基础 今日内容 ...

  10. JavaScript学习笔记01【基础——简介、基础语法、运算符、特殊语法、流程控制语句】

    w3school 在线教程:https://www.w3school.com.cn JavaScript学习笔记01[基础--简介.基础语法.运算符.特殊语法.流程控制语句][day01] JavaS ...

最新文章

  1. 魔幻!2021年,6种将死的编程语言?
  2. ubuntu16.0.4 opencv4.0.0 yolov3测试
  3. freemind的一个大bug,一周的数据啊
  4. SGU 332 Largest Circle(凸包内接圆半径nlogn)
  5. Spring boot的Hello World入门
  6. iphone黑屏转圈_iphone7无限转圈黑屏怎么回事?
  7. java中什么是守护线程_什么是Java的守护线程?
  8. 209. 长度最小的子数组
  9. mac php 403,mac下配置apache以及403问题
  10. Yandex插件使用说明——Slager_Z
  11. 【python爬虫】动漫之家漫画下载(scrapy)
  12. 粗暴解决《python数据挖掘入门与实践》第五章PCA案例中pd.read_csv函数里converters无作为的方案
  13. VMware安装macOS High Sierra 10.13苹果系统并设置共享文件夹详细教程(图文)
  14. 学习自我管理和自我营销
  15. 用C#实现一个简易的软件光栅化渲染器
  16. 从零开始Bootstrap教程
  17. 等精度测频原理--频率计
  18. android iOS App客户端如何实现在线支付
  19. 晨星评选的2020年获奖基金怎么样?
  20. 特斯拉无人驾驶最核心的人工智能算法,竟是强化学习

热门文章

  1. 我的翻转课堂教学实践
  2. 友谊:铭记恩惠忘记伤害
  3. 中国石油大学天梯赛真题模拟第三场
  4. 美的vs格力 佛山 珠海
  5. Unity实现自适应屏幕大小——九宫格
  6. 有新的CVE仓库送达~
  7. springboot实现统一日志管理
  8. Three.js 粒子系统动画与发光材质——利用HTML5画布绘制
  9. 网上流传ldquo;魔方文化启示录rdquo;
  10. 【职场攻略】送礼给老板有讲究