简介

官网:cn.vuejs.org
官方文档:https://v3.cn.vuejs.org/guide/installation.html
菜鸟:https://www.runoob.com/vue3/vue3-tutorial.html

可以联网导入,也可以下载下来本地导入。本文章全以本地导入为主
<script src="https://unpkg.com/vue@next"></script>

Hello Vue

熟悉一下语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!-- 第一步 引入vue.js文件 -->
<script src="./js/v3.2.8/vue.global.prod.js" type="text/javascript" charset="utf-8"></script>
</head>

<body>
<!-- 第二步 创建一个挂载节点 -->
<div id="app">
{{message}}
</div>

<!-- 第三步 创建Vue实例,并且绑定挂载节点 -->
<script type="text/javascript">

//声明一个常量
const app = {
data() {
return {
message: `Hello Vue`
}
}
}

//创建Vue实例,并且绑定挂载节点
Vue.createApp(app).mount("#app");

</script>
</body>

</html>

声明式渲染

插值表达式{ { } }
Vue.js 的核心是一个允许你采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统:

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="app">
<h4>{{message}}</h4>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
</script>
<script>
var app = new Vue({ //创建VM对象
el:"#app", //指定锚定DOM根元素
data:{
message:"Hello Vue.js"
}
});
</script>

参数 $event

事件对象有$event,如果需要利用必须是最后一个参数
如果事件直接绑定函数名称(不带括号),默认会传递事件对象作为事件处理函数的第一个参数

如果事件是函数调用绑定(带括号),必须显式传递事件参数对象(参数名:$event)

例子:
当你触发input事件时,$event 是当前的事件对象。
而$event.target.value指向的是当前的input的值。

1
<input @keydown.enter="test($event)">
1
2
3
4
test(event){
let num = event.target.value;
}
// 控制台就会打印出input文本框里面的值

指令

指令是带有v-开头的特殊属性,其值限定为单个表达式。
指令的作用是,当表达式的值发生变化,将其产生的连带影响应用到DOM节点中。

v-html

用于更新元素的innerHTML,该根部内容会被当做HTML代码插入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<body>
<div id="app">
<p v-html="message"></p>
</div>

<script type="text/javascript">
Vue.createApp({
data() {
return {
message: `<h1>Hello Vue.js</h1>`
}
}
}).mount("#app");
</script>
</body>

v-text

将字符串以普通文本的形式输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/v3.2.8/vue.global.prod.js" type="text/javascript" charset="utf-8"></script>
</head>

<body>
<div id="app">
<p v-text="message"></p>
</div>

<script type="text/javascript">
Vue.createApp({
data() {
return {
message: `<h1>Hello Vue.js</h1>`
}
}
}).mount("#app");
</script>
</body>
</html>

v-bind

主要用于响应更新HTML元素属性,将一个或者多个属性动态绑定到表达式。
v-bind可省略,如v-bind:src可简写为:src

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/v3.2.8/vue.global.prod.js" type="text/javascript" charset="utf-8"></script>
</head>

<body>
<div id="app">
<img v-bind:src="imgUrl" width="100" height="100" />
<!-- v-bind指令可以省略 -->
<p :title="message">把鼠标放在这里停留几秒</p>
</div>

<script type="text/javascript">
Vue.createApp({
data() {
return {
imgUrl: `https://img2.baidu.com/it/u=281572882,1041305488&fm=26&fmt=auto`,
message: "这个是绑定了title属性的p元素"
}
}
}).mount("#app");
</script>
</body>

v-model

该指令用于在表单元素中的双向数据绑定。
v-model会忽略所有表单元素的value checked、selected特性的初始值。因为它会选择vue实例的数据来作为具体的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title></title>
<script src="../js/v3.2.8/vue.global.prod.js" type="text/javascript" charset="utf-8"></script>
</head>

<body>
<div id="app">
<h2>1.文本输入</h2>
<p>{{message}}</p>
<input v-model="message" type="text" />

<h2>2.单选框</h2>
<p>{{gender}}</p>
性别:
男:<input type="radio" name="gender" value="male" v-model="gender" />
女:<input type="radio" name="gender" value="female" v-model="gender" />


<h2>3.复选框</h2>
<p>{{hobby}}</p>
爱好:
健身<input type="checkbox" value="健身" v-model="hobby" />
踢球<input type="checkbox" value="踢球" v-model="hobby" />
游戏<input type="checkbox" value="游戏" v-model="hobby" />
游泳<input type="checkbox" value="游泳" v-model="hobby" />
拳击<input type="checkbox" value="拳击" v-model="hobby" />


<h2>4.下拉选框</h2>
<p>{{city}}</p>
<select v-model="city">
<option value="0">--请选择--</option>
<option value="gz">广州</option>
<option value="nj">南京</option>
<option value="bj">北京</option>
<option value="sh">上海</option>
</select>


<hr />
<button type="button" @click="show">点击</button>
</div>

<script type="text/javascript">
Vue.createApp({
data() {
return {
message: "zhangsan",
gender: "male",
hobby: ['拳击'],
city: "0"
}
},
methods: {
show() {
//alert(this.message);
//alert(this.gender);
//alert(this.hobby);
alert(this.city);
}
}
}).mount("#app");
</script>
</body>

</html>

v-show 与 v-if

根据表达式的真假,来显示或者隐藏HTML元素。

区别:
v-show会生成节点然后使用dispaly属性进行显示和隐藏
v-if在值是false的时候不生成节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/v3.2.8/vue.global.prod.js" type="text/javascript" charset="utf-8"></script>
</head>

<body>
<div id="app">
<h1 v-show="yes">yes</h1>
<h1 v-show="no">no</h1>
<h1 v-show="age >= 26">{{age}}</h1>
<h1 v-show="name.indexOf('s') >= 0">{{name}}</h1>
</div>
<script type="text/javascript">
Vue.createApp({
data() {
return {
yes: true,
no: false,
age: 26,
name: "smith"
}
}
}).mount("#app");
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/v3.2.8/vue.global.prod.js" type="text/javascript" charset="utf-8"></script>
</head>

<body>
<div id="app">
<h1 v-if="yes">yes</h1>
<h1 v-if="no">no</h1>
<h1 v-if="age >= 26">{{age}}</h1>
<h1 v-if="name.indexOf('s') >= 0">{{name}}</h1>
</div>
<script type="text/javascript">
Vue.createApp({
data() {
return {
yes: true,
no: false,
age: 26,
name: "smith"
}
}
}).mount("#app");
</script>
</body>

v-else-if 与 v-else

互斥条件,当一个条件满足时,后续条件都不会再判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/v3.2.8/vue.global.prod.js" type="text/javascript" charset="utf-8"></script>
</head>

<body>
<div id="app">
<span v-if="score >= 95">优秀</span>
<span v-else-if="score >= 80">良好</span>
<span v-else-if="score >= 60">及格</span>
<span v-else>不及格</span>
</div>
<script type="text/javascript">
Vue.createApp({
data() {
return {
score: 79
}
}
}).mount("#app");
</script>
</body>

v-for

通过循环的方式来渲染一个列表,循环对象可以是数组,也可以是JS对象。
遍历数组语法:item in items
遍历对象语法:value,key,index in Obj

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<body>
<div id="app">
<h1>1.迭代数组</h1>
<ul>
<li v-for="(city,index) in citys">{{index + 1}}--{{city}}</li>
</ul>
<h1>2.迭代对象</h1>
<ul>
<li v-for="(value,key,index) in book">{{index}}--{{key}}--{{value}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.createApp({
data() {
return {
citys: ['广州', '南京', '上海', '北京'],
book: {
name: "《从入门到放弃》",
isbn: "1234567890",
author: "葫芦",
price: 65.00
}
}
}
}).mount("#app");
</script>
</body>

v-on

事件绑定指令,而且JS的所有事件都可以用v-on绑定

全写形式:v-on-click
简写形式:@click

其他常用事件:https://pengyirui.gitee.io/posts/d3d6.html#%E4%BA%8B%E4%BB%B6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<body>
<div id="app">
<h1>1.点击事件</h1>
{{message}}

<h1>2.焦点失去事件</h1>
<input type="text" @blur="print" />
<hr />
<button type="button" @click="changeMessage">点击改变message的值</button>
</div>

<script type="text/javascript">
Vue.createApp({
data() {
return {
message: "Hello Vue.js"
}
},
methods: {
changeMessage() {
this.message = "Hello World";
},
print() {
alert("焦点失去事件被触发...");
}
}
}).mount("#app");
</script>
</body>

绑定HTML 的class

class是每个HTML元素都有的属性。
用vue控制css样式是否生效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
.active {
width: 100px;
height: 100px;
background-color: greenyellow;
}

.border-style {
border-radius: 10px;
cursor: pointer;
}
</style>

<script src="../js/v3.2.8/vue.global.prod.js" type="text/javascript" charset="utf-8"></script>
</head>

<body>
<div id="app">
<div :class="{'active':isActive,'border-style':isBorderStyle}"></div>
<div :style=""></div>
</div>

<script type="text/javascript">
Vue.createApp({
data() {
return {
isActive: true,
isBorderStyle: true
}
},
}).mount("#app");
</script>
</body>

组件

可以 扩展 HTML 元素 和 封装 可重用的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<body>
<div id="app">
<!-- 4.可重复使用组件 -->
<first-component></first-component>
<first-component></first-component>
</div>

<script type="text/javascript">
//1.构建一个空的Vue实例
const app = Vue.createApp({});

//2.使用 vue实例构建一个组件
// first-component:自定义标签
// template:编写模板
app.component("first-component", {
template: `
<div>
<h1>Hello Component</h1>
<h2>这是我的第一个VUE组件...</h2>
</div>
`
});
//3.挂载
app.mount("#app");
</script>
</body>

局部组件注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<body>
<div id="app">
{{message}}
<login></login>
</div>
<script type="text/javascript">

Vue.createApp({
data() {
return {
message: "这是Vue实例的message"
}
},
components: {
login: {
template: `<h1>这是登录的局部组件--{{this.message}}</h1>`,
data() {
return {
message: "这是局部组件的message"
}
}
}
}
}).mount("#app");
</script>
</body>

静态值传递 props

关键字props:用于设定组件中的属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<body>
<div id="app">
<site-name title="Google"></site-name>
<site-name title="Runoob"></site-name>
<site-name title="Taobao"></site-name>
</div>

<script>
const app = Vue.createApp({})

app.component('site-name', {
props: ['title'],
template: `<h4>{{ title }}</h4>`
})

app.mount('#app')
</script>
</body>

动态值传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<body>
<div id="app">
<login :post="obj"></login>
<button type="button" @click="changeData">点击</button>
</div>

<script type="text/javascript">
Vue.createApp({
data() {
return {
obj: {
id: 1,
title: "《标题》",
content: "内容...."
}
}
},
methods: {
changeData() {
alert('点击触发事件执行');
this.obj = { 'id': 2, 'title': '关于...', 'content': '疫情防御....' }
}
},
components: {
login: {
template: `
<div>
<h1>{{post.id}}</h1>
<h1>{{post.title}}</h1>
<h1>{{post.content}}</h1>
</div>`,
props: ['post']
}
}
}).mount("#app");
</script>
</body>

计算属性 computed

是用来简化vue页面中 文本插值的js表达式。

computed 与 methods区别:
我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<body>
<div id="app">
<p>未改变之前的数据:{{message}}</p>
<p>改变之后的数据:{{upperCase}}</p>
<p>{{msg}}</p>
<button type="button" @click="upperCase1">点击</button>
</div>

<script type="text/javascript">
Vue.createApp({
data() {
return {
message: "Hello World",
msg: ""
}
},
computed: {
upperCase() {
return this.message.toUpperCase();
}
},
methods: {
upperCase1() {
this.msg = this.message.toUpperCase();
}
}
}).mount("#app");
</script>
</body>

路由

在vue的基础上,再导入路由文件
下载 或 在线导入路由:<script src="https://unpkg.com/vue-router@4"></script>

路由允许我们通过不同的url访问不同的内容
通过vue可以实现多视图的单页web应用

配置文件

router文件夹下有个index.js文件夹用来修改配置的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 导入你需要用到的.vue路由文件
// 也可以懒加载
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/components/Login'
import ProductList from '@/components/ProductList'

Vue.use(VueRouter)


const routes = [
{
// 组件的路径
path: '/',
// 组件的名字
name: 'ProductList',
// 导入的.vue组件在这里应用
component: ProductList
}, {
// 加冒号表示路由的参数(与后端的传参有关)
path: '/login/:id',
name: 'Login',
component: Login
}
]

// 这里的模式修改成这样,历史模式,(有待研究)
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})

export default router

点击切换路由

两种方法

1
2
3
4
5
6
7
8
9
10
<!-- 切换到 组件路径是/login -->
<router-link to="/login"></router-link>

<!-- 切换到组件名字是Login -->
<router-link :to="{name:'Login'}"></router-link>


<!-- 路由占位视图 -->
<!-- 切换后的位置 -->
<router-view></router-view>

获取路由的参数

注意!!!获取路由是$route没有r的!!!

1
2
3
4
this.$route.params;

// 例子:
let id = this.$route.params.id;

带参切换路由

1
2
3
// 解释:
// push({name:"路由配置文件中,需要跳转到哪个路由的名字"},query:{参数key:参数value})
this.$router.push({name:'name',query:{name:name}})

路由监听

1
2
3
4
5
watch:{
$route(){
// 监听,当路由发生变化的时候执行
}
}

跨域请求

当前端端口是8080,后端是9090时,存在跨域问题
可以改变前端端口,做跨域请求

在主目录下新建vue.config.js文件,写入以下内容(/api只是用来更好区分)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module.exports = {
devServer: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:9090',
pathRewrite: {
'^/api': '' //如果本身的路径中有api则无需此设置
}
},
}
}
}

前端将端口改为3000

例如:
后端开放的端口是127.0.0.1:9090/products
配置完后前端输入127.0.0.1:3000/api/products
获得的是相同的数据

js对象

例如构造个UserService.js

1
2
3
4
5
6
7
8
9
export default class UserService {
//构造函数
constructor() {

},

saveUser(xxx) {
// 方法体
}

使用对象

1
2
3
4
5
6
7
8
先导包
import UserService from "@/service/UserService"

实例化对象
let userService = new UserService();

使用对象中的方法
userService.saveUser(xxx);

axios

官网:https://www.npmjs.com/package/axios
vue中的ajax技术。可以理解为vue封装的ajax技术。
axios是基于vue.js开发的的,所以要先导入vue.js
下载 或 在线导入:<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

在vue里面添加
vue add axios
npm 安装
npm install axios

在vue cli 中添加axios
命令:npm导入:npm install --save axios
.vue文件中导入axios
import axios from 'axios'

1
2
3
4
5
6
7
8
语法:
axios({method,url,params}then().catch();

get语法:
axios.get('',{params}).then(resp=>{}).catch(error=>{});

post语法(需要转换):
axios.post('',{});

具体实现:把name与time发送到后台,后台发送json对象到前台

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// method:模式
// url:发送地址
// params:传送的数据
// .then(resp=>{成功后接收到的数据})
axios({
method:"post",
url:"http://localhost:8080/axiosAjax",
params:{
name:this.name,
time:"2021-10-8 16:52"
}
}).then(resp=>{
this.info = resp.data;
})

// get
axios.get('http://localhost:8080/axiosget',{
params:{
name:this.name,
time:"2021-10-8 16:52"
}
}).then(resp=>{
this.users = resp.data;
});

// post
// 注意!!!!
//处理需要发送的数据
let params = new URLSearchParams();
params.append("name",this.name);
params.append("time","2021-10-8 16:52");
//将传给服务器后台的数据封装成:name=xxx&time=2021-10-8 16:52
//然后将处理过的参数让浏览器打包发送给服务器
//使用axios发送ajax请求
axios.post('http://localhost:8080/axiospost',params).then(resp => {
this.users = resp.data;
});

传的是json对象,并且带头部

1
2
3
4
5
6
axios.post("/api/orders",JSON.stringify(order),{    //将对象格式转化为json
headers:{
"Content-Type":"application/json", //跟浏览器说这是头部参数
"key":"value" //头部需要带的参数
}
}

常用的官方解释

Method Api
GET axios.get(url).then(successCallback).catch(errorHandler)
POST axios.post(url, data).then(successCallback).catch(errorHandler)
PUT axios.put(url, data).then(successCallback).catch(errorHandler)
DELETE axios.delete(url).then(successCallback).catch(errorHandler)

GET传参:

axios.get(url,{key:value,key:value}).then(function(data){});

POST/PUT传参

(1)使用json对象传参(在服务器端控制器要求@RequestBody)—-默认方式

axios.post(url,{username:'accp',password:'123'}).then(function(data){});

(2)使用URLSearchParams传参—表单传参

1
2
3
4
5
6
7
let param = new URLSearchParams();

param.append('username', this.username);

param.append('password', this.password);

axios.post(url,param).then(function(data){});

vue cli

Vue CLI 是一个基于 Vue.js进行快速开发的一个完整的系统。
Vue CLI安装需要使用npm命令,npm命令需要基于node.js,所以要先安装node.js

node.js官网:https://nodejs.org/zh-cn/

搭建:npm install -g @vue/cli

选一个目录创建项目
vue create 项目名

进入项目目录,运行服务,用浏览器测试。
npm run serve

.vue为后缀的文件,这个文件可以包含,HTML、CSS、JS
HTML是写在<template></template>
JS是写在<script></script>
CSS是写在<style></style>

todo list 练习

一个小练习,
!(图片)[]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<!-- App.vue -->
<template>
<Head @todotitle="addtodo"></Head>
<Body :todolist="todolist" @delindex="deltodo"></Body>
<Tail :todolist="todolist"></Tail>
<br>
<button @click="loadData">加载数据</button>
<button @click="saveData">保存数据</button>
</template>

<script>
import Body from "./components/Body.vue";
import Head from "./components/Head.vue";
import Tail from "./components/Tail.vue";

export default {
name: "App",
components: {
Head,
Body,
Tail,
},

// 创造数据
data() {
return {
todolist: [
{
title: "学习ES6新语法",
finished: false,
},
{
title: "学习Spring Boot",
finished: false,
},
{
title: "背诵单词",
finished: true,
},
],
};
},

// 方法区域
methods: {

addtodo(title) {
var todo = {
title: title,
finished: false,
};
this.todolist.push(todo);
},

deltodo(index) {
this.todolist.splice(index, 1);
},
//加载数据
loadData() {
//从本地存储获取数据
var data = localStorage.getItem("todolist");
if (data) {
this.todolist = JSON.parse(data);
}
},
//保存数据
saveData() {
//将当前items中的数据存储到localStorage中
localStorage.setItem("todolist", JSON.stringify(this.todolist));
},
},
};
</script>

<style>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- Head.vue -->
<template>
<h2>Todo App</h2>
待办事务:<input type="text" v-model="title" />
<button @click="addtodo">添加</button>
<hr />
</template>

<script>
export default {
data() {
return {
title: "",
};
},
methods: {
addtodo() {
//触发自定义事件
this.$emit("todotitle", this.title);
//清空title
this.title = "";
},
},
};
</script>

<style>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!-- Body.vue -->
<template>
<table border="1">
<tr>
<td>完成</td>
<td>待办事项</td>
<td>删除</td>
</tr>
<!-- 循环 -->
<tr v-for="(todo, index) in todolist" :key="todo">
<td><input type="checkbox" v-model="todo.finished" /></td>
<td :class="{ text: todo.finished }">{{ todo.title }}</td>
<td><button @click="deltodo(index)">删除</button></td>
</tr>
</table>
</template>

<script>
export default {
props: ["todolist"],
methods: {
deltodo(index) {
this.$emit("delindex", index);
},
},
};
</script>

<style>
/* 横线样式 */
.text {
text-decoration: line-through;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!-- Tail.vue -->
<template>
<hr />
<spam>共有{{ todolist.length }}条,已完成{{finallytodo}}条,未完成{{unfinallytodo}}条</spam>

</template>

<script>
export default {
props: ["todolist"],
computed: {
// 计算已完成总数
finallytodo() {
var count = 0;
this.todolist.forEach((x) => {
if (x.finished) count++;
});
return count;
},

// 计算未完成总数
unfinallytodo() {
var count = 0;
this.todolist.forEach((x) => {
if (!x.finished) count++;
});
return count;
},
},
};
</script>

<style>
</style>

script标签

注意:自定义组件命名规则
1.短横线 my-component
2.驼峰式 MyComponent:在使用组件的时候只能在模板字符串中(组件中嵌套个组件)使用驼峰命名,在普通的标签中使用必须转换为短横线的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<script>
export default {
// 导入的包(@表示工程文件夹默认src)
import CartService from "@/service/CartService";

// 自定义使用到的模块
components: { 子组件, ... },

props:[ '属性1', '属性2', ... ],

// vue文件名字
name:"App"

//一般不用。。
template: 'html字符串模板'

// 使用到的数据
data() {
return {
name: '',
age: ''
};
},

// 立即加载的数据
mounted() {
this.name = "葫芦"
this.age = 23;
},

// 计算属性
computed: {
allQuantity() {
return this.cart.totalQuantity();
}
},

// 方法都放到这里
methods: {
eat(){
console.log("正在吃饭~~")
}
},

// 监听属性,当有xxx有改变就执行(一般放方法多)
watch:{

}
}
</script>

浏览器存储

localStoragesessionStorage一样都是用来存储客户端临时信息的对象。
localStorage生命周期是永久
sessionStorage生命周期为当前窗口或标签页

sessionStorage

将用户数据存入session

1
sessionStorage.setItem("user",JSON.stringify(user));

获取session数据

1
let user = sessionStorage.getItem("user");

json转换为Object类型

1
let user = JSON.parse(json);

Object类型 转换为json

1
let user = JSON.stringify(Object)

localStorage

localStorage保存到浏览器

1
localStorage.setItem("cart", JSON.stringify(this.items));

清空指定key的localStorage

1
localStorage.removeItem("cart");

加载localStorage

1
let cart = localStorage.getItem("cart");