目录
2.7 v-if、v-else-if、v-else和v-show
七、使用vue脚手架搭建前端工程以及使用elementUI来快速开发
一、前言
从最开始的项目介绍,架构介绍,到后面的环境搭建,然后到微服务组件的介绍,第四天迎来的前端基础环节,这个项目基础篇的主要目标就是打通全栈开发能力,当然前端也就不容忽视了。但这里的讲的前端,并不是原生的html,css和js了,默认我们都会了,其实我这些还好多都不会,说实话只学了一少部分,学的不多,看什么时候有时间好好的补一补,今天第四天主要学的是响应式框架-vue。
二、学习的内容
主要学的是vue,之前一部分学的是ES6,ES是一套规范,JS是基于这套规范的,就像Java中的JDK一样,这部分主要学的是一些新语法。后面就主要是vue了,学习vue的一些语法:指令、计算属性、监听器、过滤器、钩子函数、组件还有基于vue的脚手架开发。
一、ES6新语法
1.1 var与let
这两者都是用来声明变量的,区别在于var比较随意,而let比较严格。
var声明的变量跨块使用,而这个let不能跨块使用,就是var有点类似于全局变量。
并且var还比较放肆,可以对于同一个变量名,可以重复声明。
下面是代码例子:
<script>
{
var v = 1;
let l = 2;
}
console.log(v);
//console.log(l); // l is not defined
var m = 1;
var m = 2;
console.log(m);
let n = 1;
//let n = 3; 不可重复定义
console.log(n);
</script>
1.2 const
和c语言中的const以及Java中的final一样,都是代表声明的是常量,一旦声明好之后,就不能在被修改。
<script>
const m = 1;
//m = 2; //2. const.html:11 Uncaught TypeError: Assignment to constant variable.
console.log(m);
console.log(m);
</script>
1.3 解构表达式的使用
这个比较有意思,何为解构,就是说可以直接分解结构获取到值。其实就是一个写好了的数组或者是一个对象,我们可以很简单的获取到里面的元素赋值变量,不需要我们一个一个的自己手动的去获取。
就比如说数组就可以直接使用[变量]进行接受,如下是示例:
<script>
let arr = [1, 2, 3];
const [x, y, z] = arr;
console.log(x, y, z); //打印出1,2,3
</script>
还可以解构对象哦!如下所示:
<script>
//const {name,age} = person;
//console.log(name,age);
//可以给name起别名。注意这个变量名也不能重复
const {name:nn,age} = person;
console.log(nn,age);
</script>
1.4 字符串Api的使用
首先是很简单的字符串函数的使用:
<script>
let str = "hello world";
console.log(str.startsWith("he"));//true
console.log(str.endsWith("ld"));//true
console.log(str.includes("o"));//true
console.log(str.includes("hello"));//true
</script>
下面就是关于字符串的相关的几个方便之处,也就是 使用 ``
//多行字符串 `的使用
<script>
let ss = `<div>
<span>Hello World</span>
</div>
`
console.log(ss);
let name = "zhangsan";
let age = 20;
let info = `我是${name},今年${age}岁了`;
console.log(info);
function fun(){
return "这是一个函数";
}
let sss = `这是什么?${fun()}`;
console.log(sss);
</script>
1.5 函数优化
可以为函数的参数直接指定默认值。还可以使用可变形参和Java一样
<script>
//函数参数默认值
function add1(a,b){
b = b|2;
return a + b;
}
console.log(add1(1));
function add2(a,b=1){
return a + b;
}
console.log(add2(1));
//不定参数
function fun(...values){
console.log(values.length);
}
fun(1,2,3,4);
fun(2,3);
</script>
1.6 箭头函数
箭头函数和Java中的lambda很像,都是简便方法对象的创建。当然创建的结果不一样,JS中是函数对象,而Java不单指方法对象,而是接口实现类对象。
箭头函数可以结合解构表达式使用,在之后的前端发送请求,获取到的result对象,可以直接解构拿出其中的属性(比如说data)。直接使用{data}解构出data属性,得到后端真正发送的响应对象。
<script>
let hello = function (a,b){
return a + b;
}
console.log(hello(1,2));
//使用箭头函数
let hello1 = (a,b) => a+b;
console.log(hello1(2,3));
//箭头函数结合解构表达式
const person = {
name: "jack",
age: 20
}
//以前的方式
function hello3(person){
console.log(person.name);
}
hello3(person);
//现在结合解构表达式
let hello2 = ({name}) => console.log("name:",name);
hello2(person);
</script>
1.7 对象优化
主要就是Object类的使用、拷贝、对象的简写、对象的方法的简写、对象的拓展运算符(拷贝对象、合并对象)
<script>
//新增的Api
const person = {
name : "Jack",
age : 20,
language: ["Java","C++","Python"]
}
console.log(Object.keys(person));
console.log(Object.values(person));
console.log(Object.entries(person));
let target = {a : 1};
let resource1 = {b : 2};
let resource2 = {c : 3};
//拷贝
Object.assign(target,resource1,resource2);
console.log(target);
//声明对象简写
let name = "zhangsan";
let age = 20;
//传统的
let stu = {name: name,age: age}
console.log(stu);
//对于属性名和值变量名同名的情况,可以省略掉属性名
let stu1 = {name,age};
console.log(stu1);
//对象的方法属性简写
let dog = {
//方式一
dis:function(){
console.log("这是一条小狗");
},
//方式二
dis1:() => console.log("这是一条小狗......"),
dis2(){
console.log("这是一条小狗'''''");
}
}
dog.dis();
dog.dis1();
dog.dis2();
//对象的拓展运算符
//拷贝对象
let person1 = {name:"wangwu",age:20};
let someone = {...person1};
console.log(someone);
//合并对象
let name1 = {name:"lisi"};
let age1 = {name:"zhaoliu",age:22};
//重复的属性名,选取最后一个
let person2 = {...name1,...age1};
console.log(person2);
</script>
1.8 map和reduce
就是使用map转换集合中的元素,和Java中的有点像。但是Java中的stream流中的map需要最终进行收集。但JS不需要。另外对于运算链来计算集合中的元素则可以使用reduce,比如求得集合中所有元素的乘积或者是和等。
<script>
//map转换
let arr = [1,2,3,4];
arr = arr.map(s => s*2);
console.log(arr);
//reduce
let arr1 = [3,4,5,6];
console.log(arr1.reduce((a,b) => a+b));
//还可以指定初始值
console.log(arr1.reduce((a,b)=>a+b,1));
</script>
1.9 promise异步编排
promise存在的意义其实就是为了使代码变得清晰,而不混乱。解决的是链式调用的嵌套问题。就比如说不用promise之前,如果每次返回的结果又作为下次的请求参数,如果请求次数多了那么嵌套的层数也就多了,就比如说下面这个例子:
下面是user.json文件,存放着用户的姓名以及学生编号:
{
"userName": "wangwu",
"userId":5
}
下面是user_course_5.json文件,存放着学生编号为5的学生的课程信息,包含课程名称以及课程编号:
{
"courseName" : "Math",
"courseId" : 10
}
下面是course_score_10.json文件,存放着课程编号为10的课程成绩:
{
"score" : 100
}
传统的方式是下面这个样子:
$.ajax({
url: "mock/user.json",
success(data) {
console.log("查询用户:", data);
$.ajax({
url: `mock/user_corse_${data.id}.json`,
success(data) {
console.log("查询到课程:", data);
$.ajax({
url: `mock/corse_score_${data.id}.json`,
success(data) {
console.log("查询到分数:", data);
},
error(error) {
console.log("出现异常了:" + error);
}
});
},
error(error) {
console.log("出现异常了:" + error);
}
});
},
error(error) {
console.log("出现异常了:" + error);
}
});
很明显,代码很混乱,多层的嵌套。
于是promise的作用就体现出来了,promise能很清晰的知道一层一层的往下传递,结果很清晰,
如下:
<script>
使用promise处理多层的嵌套
new Promise((resove,reject)=>{
$.ajax({
url: "mock/user.json",
success(data){
console.log("查询用户:",data);
resove(data.userId);
},
error(error){
console.log("出现异常了,",error);
}
}
)
}).then((userId) =>{
return new Promise((resove,reject)=>{
$.ajax({
url: `mock/user_course_${userId}.json`,
success(data){
console.log("查询课程:",data);
resove(data.courseId);
},
error(error){
console.log("出现了异常,",error);
}
})
})
}).then((courseId)=>{
new Promise((resove,reject)=>{
$.ajax({
url: `mock/course_score_${courseId}.json`,
success(data){
console.log("查询成绩:",data);
},
error(error){
console.log("出现了异常,",error);
}
})
})
})
</script>
使用resove方法将成功的结果一步一步的往下传递。每次使用promise对象对每次调用进行处理。
当然实际开发中,追求尽可能的通用,简洁。于是可以将一次处理就返回一个promise对象作为一个方法的返回值。
//优化
<script>
let get = function(url,data){
return new Promise((resove,reject)=>{
$.ajax({
url: url,
type: "get",
data: data,
success(res){
resove(res);
},
error(error){
reject(error);
}
})
})
}
get("mock/user.json")
.then((result)=>{
console.log("查询到用户:",result);
return get(`mock/user_course_${result.userId}.json`);
})
.then((result)=>{
console.log("查询到课程:",result);
return get(`mock/course_score_${result.courseId}.json`);
})
.then((result)=>{
console.log("查询到分数:",result);
})
</script>
1.10 模块化(export和import的使用)
和Java一样,如果不是使用的自己造的东西,而是使用的别人的,就需要从外界导入进来,同样使用import关键字。
下面是导出的例子,语法是使用export关键字进行导出,可以导出JS中的任何变量。并且有一些简洁的方式,如下:
//先声明好对象,写好对象名,然后直接使用对象名导出即可
const util = {
sum(a,b){
return a + b;
}
}
export {util};
//还可直接导出,就是将export和导出的内容连成一句话
export const util = {
sum(a,b){
return a + b;
}
}
//还可以不指定对象的名字,这样在其它文件中导入的时候可以不指定名字,只需写明正确的路径即可
export default {
sum(a,b){
return a + b;
}
}
//除了对象,其它任何js变量都可以导出,数组,函数,基本类型变量
let name = "Jack";
let age = 20;
export {name,age};
下面是导入的例子, 使用import xxx(变量名) from 文件路径的语法进行导入。
//导入的对象的名字和从哪个文件导入的位置写好
import { util } from "./hello";
//当是默认导出的时候,名字可以随便取
import { util1 } from "./hello";
//导入基本数据类型,并不是完全都要导入的,导入我们所需要的即可
import { name,age } from "./hello";
二、vue中的常用指令
2.0 vue环境的搭建
首先,但凡是环境的搭建,都可以参考官方的文档,翻阅vue的官方文档可以知道,vue的环境搭建,可以有下面的三种方式:
1. 直接引入vue的js文件,可以是直接使用script直接引入网址或者是引入离线的文件
2. 使用DNS的方式
3. 使用node.js的npm下载工具vue工程
官方推荐使用npm的方式进行搭建。
既然要使用npm的方式,npm又是依赖于node.js的环境的,所以得首先在本地下载好node.js的环境。
下载的步骤如下:
1)、官网下载安装 node.js,并使用 node -v 检查版本
2)、配置 npm 使用淘宝镜像 npm config set registry http://registry.npm.taobao.org/
3)、大家如果 npm install 安装依赖出现 chromedriver 之类问题,先在项目里运行下面命令 npm install chromedriver --chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver 然后再运行 npm install
创建vue的简单项目步骤如下:
1. 在本地创建好一个文件夹,使用vscode进行打开
2. 使用vscode的终端执行 npm install -y的命令,项目会生成package-lock.json的文件,这个文件类似于Maven的pom文件,是用来管理依赖的
3. 使用 npm install vue的命令,给当前项目下载vue,项目下面会多出来node_modules文件夹,这个文件夹下面有vue文件夹。(之后使用script标签导入vue的环境就是靠这个vue文件夹中的dist目录下的vue.js文件)。当没有vue.js文件的时候,可以下载vue2版本,使用 npm install vue@2命令下载版本2的vue
这是创建的vue项目的大致样子:
使用src文件夹来放置源代码。
2.1 简单例子
下面这个例子,简单的体会vue这种“去掉对dom元素直接操作”的思想,其实也就是MVVM的思想,前面的MV指的是Model(模型,也就是数据)和View(也就是视图,将数据进行展示的),
最后的VM也就是View-Model 视图和模型间的双向操作,这里无需开发人员干涉,开发人员不在需要关注DOM操作,只需要关心 :数据怎么来,界面怎么画,数据怎样渲染到界面里面去。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="/node_modules/vue/dist/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="num"><br>
我是{{name}},今年{{age}}岁了<br>
<h2>有{{num}}个人为我点赞</h2><br>
<button v-on:click="num++">增赞</button>
</div>
<script>
let vm = new Vue({
el : "#app",
data :{
name: "zhangsan",
age:20,
num: 0
}
})
</script>
</body>
</html>
其中简单的涉及到 事件,双向绑定,以及插值表达式的使用
2.2 v-text、v-html
我们知道可以使用插值表达式拿出Model中的数据进行显示,其实也可以使用v-text将数据进行显示,但是这是使用在标签里面,另外当字符串为一段HTML代码的时候,不想要它直接显示,而是解析HTML代码,进行显示就使用v-html指令。下面是代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="/node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
下面是一段普通文本:<br>
<span v-text="text"></span><br>
下面是一段Html代码:<br>
<span v-html="htmlStr"></span>
</div>
<script>
let vm = new Vue({
el: "#app",
data(){
return {
text:"<h1>普通文本</h1>",
htmlStr:"<h1 style='color:red'>你好</h1>"
}
}
})
</script>
</body>
</html>
效果:
2.3 v-bind
其实也就是动态的改变html或者是css的自带属性中的属性值的可以,我反正感觉就是这个作用,包括 <a>标签,class属性,以及style属性等,在后面还有key,用来区分每一行li或者是tr
下面是示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="/node_modules/vue/dist/vue.js"></script>
<div id="app">
<a v-bind:href="link">百度一下</a><br>
<span v-bind:class="{active:isActive,'text-danger':hasError}" :style="{color:color1,fontSize:size}">
你好
</span>
</div>
</head>
<body>
<script>
new Vue({
el : "#app",
data() {
return {
link:"www.baidu.com",
isActive:false,
hasError:true,
color1:'red',
size: '36px'
}
}
})
</script>
</body>
</html>
注意:现在这些属性值是使用{}进行包裹,其实也就是一个对象,所以里面使用逗号分隔,另外,属性名如果带上了 ‘-’那么需要使用 一对 ' ' 单引号括起来,可以使用bool值来确定某个样式是否存在,以及通过model中的值动态指定样式。
2.4 v-model
双向绑定指令,相较于单向绑定,只能使用模型改变视图,而不能视图改变模型。这在开发中有个时候是不方便的,例如表单,以及复选框等结构。
下面这个示例中,使用v-model处理复选框,使得我们通过视图所选的值,也能更新到模型中。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="/node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
擅长的语言:<br>
<input type="checkbox" value="Java" v-model="language">Java<br>
<input type="checkbox" value="C++" v-model="language">C++<br>
<input type="checkbox" value="Python" v-model="language">Python<br>
</div>
<script>
let vm = new Vue({
el: "#app",
data(){
return{
language:[]
}
}
})
</script>
</body>
</html>
2.5 v-on
这个指令就是绑定事件的,常见的比如说绑定单击事件click,鼠标单击事件,键盘按下事件等。
今天学的就是这个,单纯的绑定一个事件比较简单,比较需要注意的是,绑定的那个事件的执行可以不是函数,可以是js代码段,另外还需要理解事件修饰符的使用(可以利用这个来对事件进行控制,比如说阻止事件冒泡,限制事件的执行次数等)。
还有按键修饰符的使用,其实就是绑定的按下键盘事件。
这里着重的解释下 事件修饰符的使用:
1. `.stop` :阻止事件冒泡到父元素
2. `.prevent`:阻止默认事件发生
3. `.capture`:使用事件捕获模式
4. `.self`:只有元素自身触发事件才执行。(冒泡或捕获的都不执行)
5. `.once`:只执行一次
下面解释事件冒泡:
怎样理解呢?可能有小伙伴不理解冒泡的意思,其实就是像气泡一样,从下往上冒上去。
但这里冒的不是气泡,是函数。
就比如说两个div盒子是嵌套的,如果是两个盒子上面给单击事件绑定了相同的方法的话,那么点击里面的盒子,那么会将那个函数执行两次,原因很简单,因为点击了里面的盒子,实际上也是点击了外面的那个盒子。
使用.stop指令则更好可以阻止冒泡,给里面那个盒子加上这个,就能阻止冒泡上去。
而.capture是来干啥的呢?加上了它,其实就是跌倒冒泡的顺序,加上了它,就会执行最外层盒子的事件。
这个事件修饰符可能不是那么好理解,那我直接给出示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="/node_modules/vue/dist/vue.js"></script>
<style>
.common{
border: 1px solid red;
padding: 20px
}
</style>
</head>
<body>
<div id="app">
<!-- 事件中直接写js片段 -->
<button v-on:click="num++">点赞</button><br />
<!-- 事件中写函数 -->
<button @click="cancel">取消</button><br />
<h2>当前有{{num}}个赞</h2>
<!-- 事件修饰符 -->
<div style="border: 1px solid red; padding: 20px" @click.once="dis()">
大div
<div style="border: 1px solid blue; padding: 20px" @click.stop="dis()">
小div <br />
<a href="http://www.baidu.com" @click.prevent>百度一下</a>
</div>
</div>
<!-- 测试capture修饰符:打乱冒泡顺序 -->
<div class="common" @click.capture="outer">
<div class="common" @click.capture="middle">
<div class="common" @click="innerdiv">
<button @click="inner">点击我(^_^)</button>
</div>
</div>
</div>
<!-- 按键修饰符 -->
<input type="text" @keyup.enter="enter"><br>
<input type="text" @keyup.alt.67="altc">
</div>
<script>
let vm = new Vue({
el: "#app",
data() {
return {
num: 0,
};
},
methods: {
cancel() {
this.num--;
},
dis() {
alert("被点击");
},
outer() {
console.log("outer,最外面的div被点击了");
},
middle() {
console.log("middle,中间的div被点击了");
},
inner() {
console.log("inner,最里面的按钮被点击了");
},
innerdiv(){
console.log("最里面的div被点击了");
},
enter(){
alert("按下了回车键");
},
altc(){
alert("按下了Alt+C的组合键");
}
},
});
</script>
</body>
</html>
上面那个例子没啥好说的,大div只会执行一次函数,因为.once,并且点击里面的盒子也只会执行一次,因为在里面这个盒子加上了.stop阻止冒泡到上面那个盒子,而如果点击百度一下,则只会执行里面这个盒子的函数,因为没有阻止冒泡,并且.prevent了,所以默认的事件(也就是原本的点击超链接跳转网页的这个事件)被禁止里面,因此也就不会跳转到百度网站去了。
下面的这一组div是为了测试.capture事件修饰符的,也就是打乱冒泡的顺序。原本本应该是从里往外进行冒泡的,但是现在加上了这个,使得最外面的盒子先是响应,先执行函数,其实也就是先执行离得最远的盒子绑的事件。所以运行结果是下面这样:
outer,最外面的div被点击了
middle,中间的div被点击了
最里面的div被点击了
inner,最里面的按钮被点击了
因为第三个盒子没有加上这个修饰符,因此按照正常顺序执行,也就是里面的盒子先冒泡。
2.6 v-for
v-for这个标签就是遍历的元素的,可以遍历数组,也可以遍历对象,到那个元素上面进行遍历呢?一般是 li 或者是 table中的tr
下面这个例子就是演示使用li这个元素来遍历 数组和对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="/node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<!-- 加上key可以提高渲染效率 -->
<li v-for="user,index in users" :key="index">
{{index}} => {{user.name}} => {{user.gender}} => {{user.age}}
</li>
</ul>
<ul>
<li v-for="(value,key,index) in user">
{{index+1}} => {{key}} => {{value}}
</li>
</ul>
</div>
<script>
let vm = new Vue({
el: "#app",
data() {
return {
users: [
{ name: "柳岩", gender: "女", age: 21 },
{ name: "张三", gender: "男", age: 18 },
{ name: "范冰冰", gender: "女", age: 24 },
{ name: "刘亦菲", gender: "女", age: 18 },
{ name: "古力娜扎", gender: "女", age: 25 }
],
user:{
name: "张三",
gender: "男",
age: 20
}
};
},
});
</script>
</body>
</html>
注意:可以加上索引,索引都是指明在最后,可以使用索引来作为:key的值,可以提高渲染的速度。当遍历对象时,可以同时获取到对象的key value 和 index 但是是按照这个顺序的,缺少了的话,就相当于少了后面,比如只写两项那么index就没有了。其中无论是遍历数组还是遍历对象都可以省略圆括号。
2.7 v-if、v-else-if、v-else和v-show
v-if 以及 v-show都是根据model中的布尔值来决定元素是否存在,当然只有是v-if当布尔值为false的时候,这个dom元素才是真的没有,而v-show只是改变了样式,加了个style="display:none"
因此v-if的开销更大,因此能使用v-show,尽量使用v-show。
这个命令很简单,很程序设计语言中使用没有区别,下面给出简单的示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="/node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="show = !show">点我呀</button><br>
<!-- v-if是将整个dom删掉 -->
<h1 v-if="show">
看到我了
</h1>
<!-- v-show是改变样式 -->
<h1 v-show="show">
看到我了--show
</h1>
<!-- v-else-if v-else -->
<button @click="random = Math.random()">
点我呀
</button><br>
<span>{{random}}</span>
<h1 v-if="random>=0.75">
看到我啦?random>=0.75
</h1>
<h1 v-else-if="random>0.5">
看到我啦?random>0.5
</h1>
<h1 v-else-if="random>0.25">
看到我啦?random>0.25
</h1>
<h1 v-else>
看到我啦?random<=0.25
</h1>
</div>
<script>
new Vue({
el : "#app",
data(){
return {
show : true,
random:1
}
}
})
</script>
</body>
</html>
三、vue中的计算属性和监听器
计算属性和监听器差不蛮多,计算属性其实就是监听结果,而监听器则是监听某个变量。
计算属性和监听器,现在是vue实例对象形参对象中的又一属性了,和el以及data平级。
里面放的都是函数,函数名就是监听的对象。
给出下面这个简单的示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="/node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<li>
西游记:价格{{xyjPrice}},数量:<input type="number" v-model="xyjNum">
</li>
<li>
水浒传:价格{{shzPrice}},数量:<input type="number" v-model="shzNum">
</li>
<li>
总价:价格{{zongPrice}}
</li>
{{msg}}
</ul>
</div>
<script>
let vm = new Vue({
el : "#app",
data(){
return{
xyjPrice:29.14,
shzPrice:43.53,
xyjNum:1,
shzNum:1,
msg:""
}
},
//计算属性
computed:{
//函数名就是最后要实时计算的结果
zongPrice(){
return this.xyjPrice*this.xyjNum + this.shzPrice*this.shzNum;
}
},
//监听器
watch:{
xyjNum(newVal,oldVal){
if(newVal>3){
this.msg = "西游记的库存不足";
this.xyjNum = 3;
}else{
this.msg = "";
}
}
}
})
</script>
</body>
</html>
计算属性里面有一个zongPrice名字的函数,其实就是监听zongPrice这个结果
而监听器里面则是有一个xyjNum名字的函数就是监听xyjNum值的变化,当值发生变化的时候,可以进行一段逻辑处理,比如这里对数量进行一个限制,形参可以接受两个参数,分别是新值和旧值。当然计算属性函数的返回值是一个结果,因为是“计算” 。
四、vue中的过滤器
过滤器其实就是可以对值进行转换的,比如一个经典的例子就是将使用数字表示的状态,转为对应的文字信息,之前是通过三元运算符来实现的,但是这种方式,代码是硬编码了,有代码侵入的风险,并且也不是很灵活。
下面这个例子就是转换性别:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="/node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<table>
<tr v-for="user in userList">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<!-- 以前的写法 -->
<!-- <td>{{user.gender==='1'?"男":"女"}}</td> -->
<!-- 使用过滤器的写法 -->
<td>{{user.gender | genderFilter}}</td>
</tr>
</table>
</div>
<script>
//全局过滤器
Vue.filter('genderFilter',function(gender){
return gender==='1'?"男":"女";
})
var vm = new Vue({
el : "#app",
data(){
return{
userList:[
{id:1,name:'Jack',gender:'1'},
{id:2,name:'Mary',gender:'0'}
]
}
}
//局部过滤器
// filters:{
// genderFilter(gender){
// return gender==='1'?"男":"女";
// }
// }
})
</script>
</body>
</html>
可以使用全局过滤器,以及使用局部的过滤器。
在script标签下写上下面这样:
//全局过滤器
Vue.filter('genderFilter',function(gender){
return gender==='1'?"男":"女";
})
而不是定义在Vue示例里面就是使用全局声明,之后的组件也类似。
具体怎样使用这个过滤器呢?
<td>{{user.gender | genderFilter}}</td>
这样使用,也就是使用 | 前面放上要处理的数据,后面放上过滤器。
局部的话,就像计算属性和监听器一样,Vue示例中的属性。
//局部过滤器
filters:{
genderFilter(gender){
return gender==='1'?"男":"女";
}
}
就像这样,方法名就是过滤器的名字。局部的只能在这个Vue示例所包围的范围进行使用,例如这个例子就只能在div这个标签中使用。
五、钩子函数
钩子函数其实就是关联着Vue的生命周期中的各个阶段的函数。
要知道在生命周期中大致有以下的几种状态:
1. beforeCreated:也就是Vue实例刚刚创建之前,连Model中的数据都没有填充上。是未定义的状态
2. created:刚刚创建好Vue实例,现在Model中的数据填充上了。
3. beforeMount:渲染之前,就是Model中的数据还未渲染到View视图中,此时查看视图,会发现{{name}}这样。
4. mounted:视图已经渲染好数据了,数据可以正常显示了
5. beforeUpdated:这个其实就是更新之前,就是Model中的数据已经更新了,但是这个更新还没有同步到视图里面去。
6. updated:视图中的数据也已更新。
例子:
<body>
<div id="app">
<span id="num">{{num}}</span>
<button v-on:click="num++">赞!</button>
<h2>{{name}},非常帅!!!有{{num}}个人点赞。</h2>
</div>
</body>
<script src="/node_modules/vue/dist/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
name: "张三",
num: 100
},
methods: {
show() {
return this.name;
},
add() {
this.num++;
}
},
beforeCreate(){
console.log("=========beforeCreate=============");
console.log("数据模型未加载:" + this.name, this.num);
console.log("方法未加载:" + this.show());
console.log("html 模板未加载:" + document.getElementById("num"));
},
created: function () {
console.log("=========created=============");
console.log("数据模型已加载:" + this.name, this.num);
console.log("方法已加载:" + this.show());
console.log("html 模板已加载:" + document.getElementById("num"));
console.log("html 模板未渲染:" + document.getElementById("num").innerText);
},
beforeMount() {
console.log("=========beforeMount=============");
console.log("html 模板未渲染:" + document.getElementById("num").innerText);
},
mounted() {
console.log("=========mounted=============");
console.log("html 模板已渲染:" + document.getElementById("num").innerText);
},
beforeUpdate() {
console.log("=========beforeUpdate=============");
console.log("数据模型已更新:" + this.num);
console.log("html 模板未更新:" + document.getElementById("num").innerText);
},
updated() {
console.log("=========updated=============");
console.log("数据模型已更新:" + this.num);
console.log("html 模板已更新:" + document.getElementById("num").innerText);
}
});
</script>
运行结果:
六、vue中组件的使用
组件其实可以看作就是一种复用的模板,就是抽取出来的,满足程序设计的高复用性的特点。
组件其实和Vue实例没有区别,只不过这里因为是要复用了,因此不能只挂载到某个界面上面,而是拿着这个组件就相当于一个独立的东西,直接可以进行显示,因此有一个模板template,然后后面的部分就和Vue实例一样了,也可以声明函数,data。
只要声明好了,直接用就行了,局部的就只能在Vue所挂载的范围进行使用,而全局则在当前页面那里都可以进行使用。
这里局部和全局和过滤器真的很像;
在Vue实例的外面写上这个:
Vue.component('rounter',{
template:'<button @click="count++">你点了我{{count}}次,我记住了</button>',
data(){
return {
count: 0
}
}
})
就代表声明了一个名为rounter的全局组件。注意组件里面的data写成函数的形式。
那么就可以直接这样使用:
<div id="app">
<button @click="count++">你点了我{{count}}次,我记住了</button>
<rounter></rounter>
<rounter></rounter>
<rounter></rounter>
</div>
而局部就和过滤器、计算属性、监听器一样声明一个和el以及data并行的结构,使用components这个属性,里面定义各种各样的组件。就比如下面这样:
const rounter = {
template:'<button @click="count++">你点了我{{count}}次,我记住了</button>',
data(){
return {
count: 0
}
}
};
//定义局部组件
components:{
rounter:rounter
}
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="/node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="count++">你点了我{{count}}次,我记住了</button>
<rounter></rounter>
<rounter></rounter>
<rounter></rounter>
</div>
<script>
//定义全局组件
Vue.component('rounter',{
template:'<button @click="count++">你点了我{{count}}次,我记住了</button>',
data(){
return {
count: 0
}
}
})
const rounter = {
template:'<button @click="count++">你点了我{{count}}次,我记住了</button>',
data(){
return {
count: 0
}
}
};
new Vue({
el: "#app",
data(){
return{
count:0
}
},
//定义局部组件
components:{
rounter:rounter
}
})
</script>
</body>
</html>
七、使用vue脚手架搭建前端工程以及使用elementUI来快速开发
这里的介绍在我的另外一篇博文里:
三、完成的进度
ES的这些新语法都写了一遍,以及Vue的各种指令还有一些计算属性、监听器、过滤器、组件这些都写了一遍例子。但是并不是一天之内完成的,断断续续的几天。在这几天中补其它文章了。
四、总结
主要就是熟悉ES的几个新的语法,以及熟悉vue的这几种基础语法。