三、内容:
一、MVVM
View层
- 视图层,我们前端开发时候的DOM层
- 主要就是给用户展示各种信息
Model层
- 数据层:可能是我们固定的思数据,更多的是来自我们的服务器,在网路上请求下来的数据
VueModel层
- 视图模型层
- 视图模型层是View和Model沟通的桥梁
- 一方面实现Data Binding(数据绑定), Model的改变反映到View
- 另一方面实现Dom Listener
二、Vue的生命周期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-St4dNFG8-1611487584713)(36A4E1631C5B42C7A4767AF678DC320E)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ISB5XFUh-1611487584717)(AE5CB6C9476A440CB32319EF5D96001B)]
三、基础语法
1.Mustache
在挂载id的div里面写{{内容来使用}}
2.v-once
执行一次性的插值,当数据改变的
ps:后面不需要跟任何表达式
3.v-html
解析并且渲染v-html后面跟的html
4.v-text
- v-text:将数据显示在界面中
- v-text 通常情况需要接受一个string类型
5.v-pre
- 对代码原封不动 不做任何处理
6.v-cloak
- 将未解析出来的代码块进行隐藏
7.v-bind
- 作用:动态绑定属性
- 比如:
<a :href="link">Vuejs官网</a>
v-bind绑定class
- 对象写法
用法一:可以直接通过{} 绑定一个类
<h2 :class="{'active':isActive}">Hello World</h2>
用法二:也可以通过判断,传入多个值
<h2 :class="{'active':isActive , 'line': isLine}">Hello World</h2>
用法三:和普通类同时存在 不冲突
用发丝如果太过复杂,可以放在一个Methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello World</h2>
- 数组写法
需要在外面套一个li标签,在li里面进行一个v-for遍历存在于data里面的数组
绑定style的两种方式
对象写法:
:style="{color:currentColor, fontSize :fontSize + 'px'}"
数组写法:
<div v-bind:style="[baseStyles,overridingStyles]"></div>
计算属性 computed
模板可以通过插值语法显示一些data中的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SQ6nTuYl-1611487584719)(0411889317D6467199EB517B8280F7D4)]
计算属性的setter和getter
-
每个计算属性都包括一个setter和Getter
-
在某些情况下,可以提供一种setter方法
methods和computed看起来都可以实现我们的方法,为什么还要多个计算属性呢
原因:计算属性会进行缓存,如果多次使用,计算属性只会调用一次
computed和methods的核心与区别
-
computed是属性调用,methods是函数调用
-
computed带有缓存功能,methods并不是
-
computed是用属性方式调用不需要加()
-
methods是以方法的形式调用需要加()
-
对于复杂逻辑计算,可以用computed
-
computed依赖于data中的数据,只有在他的相关依赖数据发生改变的时候才会重新求值
7.v-on事件监听
v-on介绍:
作用:绑定事件监听器
缩写:@
预期:Function|Inline Statement | Object
参数: event
8.v-if和v-show
v-if是动态的向DOM树添加或者删除DOM元素;v-show是通过设置DOM元素的display样式来控制显隐
9.v-for
<li v-for="(value,key,index) in info">{{value}}-{{key}}-{{index}}<li>
检测数组更新
- push()
- pop()
- shift()
- unshift
- splice()
- sort()
- reverse()
10-v-model
v-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">
修饰符:
lazy修饰符:
- 默认情况下,v-model默认是在input事件中同步输入框的数据的
- 也就是说,一旦有数据发生改变对应的data中的数据也会发生改变
- lazy修饰符可以让数据失去焦点或者回车时候才会更新
number修饰符:
- 默认情况下,在输入框无论我们输入的是字母海慧寺数字都会被当成字符串进行处理
- 如果我们希望处理的是数组,最好直接将内容当做数字处理
trim修饰符:
- trim修饰符可以过滤内容两边空格
四、组件化开发:
注册组件:
- 创建组件构造器
- 注册组件
- 使用组件
查看运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JRii22vF-1611487584723)(D89A12BE329D4F8194E649F9496AF79C)]
组件其他补充
全局组件和局部组件
- 当我们调用Vue.component()注册组件时候,组件注册是全局的
父组件和子组件:
- 组件和组件之间存在层级关系
注意:当子组件汉族测到父组件的Components,Vue回编译好父组件的模块
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z1Qu9X6Q-1611487584725)(38C4C7FA3AF84A07B1D104A03E6F1D49)]
注册组件语法糖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y5H9938h-1611487584727)(79639BF033F241B687B2462290899FA1)]
组件数据的存放:
如果将所有的数据都放在Vue实例中,Vue实例就会变得很臃肿
结论:Vue组件应该有自己保存数据的地方
为什么data再组件里面必须是一个函数呢?
- 如果不是一个函数,Vue会直接报错
- 其次,原因是让Vue中的每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件再多次使用后会互相产生影响
- 如图[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lnevJEGV-1611487584728)(C:\Users\丿剑来·\Pictures\youdao\review-reference.png)]
父子组件通信
父子访问形式:$children:
父组件访问子组件: c h i l d r e n 或者 children或者 children或者refs
子组件访问父组件:使用$parent
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M0nYdVcT-1611487584730)(484D20FBE6C24869AE5904C2B2CE2692)]
父子组件的访问方式:$refs
$children的缺陷:
- $children访问子组件时候,是一个数组类型,访问其中的子组件必须通过索引值
- 但是当子组件过多,我们需要拿到其中一个,往往不能缺定它的索引值
- 有时候,我们像明确取一个特定组件,这个时候就可以用到$refs
$refs:
- $refs和ref指令通常是一起使用的
- 首先,我们通过ref某一个子组件绑定一个特定的ID
- 其次,通过this.$refs.ID就可以访问了
非父子组件通信:
$dispatch:向上派发事件
$broadcast:向下级广播事件
插槽Slot
编译作用域:
父组件模板的所有东西都会在符集作用域内编译;子组件模板的所有东西都会在子级作用域内编译
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9NLGoFea-1611487584731)(7B03C79644EF46EC854BDA94628A09E5)]
具名插槽Slot
属性:name
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h7QPG2m3-1611487584732)(28CF2025AAD745DF80A55CDA9F6CFB4E)]
作用域插槽:略
五。模块化开发
在多人同时分布开发的时候可能会发生重名的问题
解决方案:
- 1.匿名函数解决方案
(function(){
var flag = true
})()
但是如果我们希望能够在main.js中用到flag
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IelsohLo-1611487584733)(A1820B1171C04A77B0097B02C2E5C6BD)]
CommonJS(了解)
模块化有两个核心:导入和导出
//CommonJS的导入
module.exports ={
flag:true,
test(a,b){
return a + b;
},
demo(a,b){
return a * b
}
}
//CommonJS的导入
//require是指的是导入
let{test , demo , flag} = require('moduleA');
<=>
let _mA = require('moduleA');
let test = _mA.test;
let demo = _mA.demo;
let flag = _mA.flag;
ES6的导出
let name ="myname"
let age = 19
let height = 181
export {name,age,height}
export default (导入者可以自己来命名)
import的使用
- 导入的实现我们需要引入js文件,并且类型需要设置为module类型
<script src="info.js" type="module"></script>
import {name , age , height} from "./info.js"
但是通常情况下我们会把{name,age,height} 化作别名以便于后续的使用
import *as info from './info.js'
图书馆系统
<!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>Document</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>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in books">
<td>{{item.id}}</td>
<td>{{item.author}}</td>
<td>{{item.name}}</td>
<td>{{item.data}}</td>
<td>{{item.price | showPrice}}</td>
<td>
<button @click="decrement(index)" :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}}</h2>
</div>
<h2 v-else>
购物车为空
</h2>
</div>
<script src="../js/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
style:
table{
border: 1 px solid #e9e9e9;
border-collapse: collapse;
border-spacing: 0;
}
th, td{
padding: 8px 16px;
border:1 px solid #e9e9e9;
text-align: left;
}
th{
background-color: #f7f7f7;
color: #5c6b77;
font-weight:600;
}
js
const app = new Vue({
el:"#app",
data:{
books:[
{
id: 1,
author: '曹雪芹',
name: '红楼梦',
data:"????-??-??",
price: 32.0,
count: 1
}, {
id: 2,
author: '施耐庵',
name: '水浒传',
data:"????-??-??",
price: 30.0,
count: 1
}, {
id: '3',
author: '罗贯中',
name: '三国演义',
data:"????-??-??",
price: 24.0,
count: 1
}, {
id: 4,
author: '吴承恩',
name: '西游记',
data:"????-??-??",
price: 20.0,
count: 1
}
]
},
methods:{
decrement(index){
this.books[index].count--;
},
increment(index){
this.books[index].count++;
},
removeHandler(index){
this.books.splice(index, 1);
},
},
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;
}
},
//全局过滤器 ,filter 不能定义在创建的Vue对象后面 ,filters局部过滤器
filters:{
showPrice(price){
return "¥" + price.toFixed(2);
}
},
})