vue

什么是vue

vue是js框架,也就是一堆写好的代码

简单的使用例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="app">
<h1>{{ title }}</h1>
</div>
<script>
Vue.createApp({
data() {
return {
title: '零食清单'
}
}
}).mount('#app');
</script>
</body>

</html>

在以上的代码中 有三个关键部分

  • 6:script标签导入vue

    若不想经过构建流程就可以使用vue,可以这么做(CDN方式构建)(CDN的地址以后可能有变动)

  • 13:createApp()函数创建新实例

    • createApp()函数有可选参数,类型是对象{}

    • createApp()传入了一个对象:

      1
      2
      3
      4
      5
      6
      7
      {
      data(){
      return {
      title: '零食清单'
      }
      }
      }

      这个对象有一个data()方法,返回值中有title,title值为“零食清单”

    • 函数后面跟了.mount(“#app”),也就是调用了mount方法挂载在了dom中的id为“app”的标签上,也就是:

      Vue.createApp({}).mount(“#app”)

  • 10: 插值表达式

    Vue初学,一个类似于这样的结构,data()返回值title插入到此处,并在页面中显示。

这就是vue一个简单的使用方法


v-for循环打印列表

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="app">
<h1>{{ title }}</h1>
<ul>
<li v-for="item in food">
<span>{{ item.name }}</span>
<img v-bind:src="item.img" alt="img">
<input type="checkbox" v-model:"item.purchased">
<span>{{ item.purchased }}</span>
</li>
</ul>
</div>
<script>
Vue.createApp({
data() {
return{
title: '零食清单',
food: [
{id: 1, name: '原味鱿鱼丝', img: './images/1.png', purchased: false },
{id: 2, name: '辣味鱿鱼丝', img: './images/2.png', purchased: false },
{id: 3, name: '碳味鱿鱼丝', img: './images/3.png', purchased: false },
]
}
}
}).mount('#app');
</script>
</body>
</html>
  • v-for使用方法

    1
    2
    3
    4
    <ul>
    <li v-for="item in list"></li>{{item.name}}</li>
    <!-- 这里的list是一个数组 -->
    </ul>
  • return中的值可以为数组

    如:

    1
    2
    3
    4
    5
    6
    7
    return{
    title:'xxx',
    list: [
    {id: 1, name: first},
    {id: 2, name: second}
    ]
    }
  • v-bind单向数据绑定

    绑定后,vue的数据改变会影响dom,而dom对数据作修改不会影响vue中的数据

    注意:当元素的属性值是动态的时候应该用到v-bind属性。

    如:

    1
    2
    3
    <ul>
    <li v-for="item in items" v-bind:id="item.id">{{ item.id }}</li>
    </ul>
  • v-model双向数据绑定

    绑定后,dom和vue中的数据相互影响。

箭头函数

例:

1
food => food.value

这里 将food作为参数传入函数里,函数体为food.value

就这么简单

key、v-show、computed()

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="app">
<h1>{{ title }}</h1>
<section v-show="food.filter(item => !item.purchased).length">
<h1>未购买</h1>
<ul>
<li v-for="item in food.filter(item => item.purchased == false)" :key="item.id">
<span>{{ item.name }}</span>
<input type="checkbox" v-model="item.purchased" >
<span>{{ item.purchased }}</span>
</li>
</ul>
</section>
<section v-show="food.filter(item => item.purchased).length">
<h1>已购买</h1>
<ul>
<li v-for="item in food.filter(item => item.purchased)" :key="item.id">
<span>{{ item.name }}</span>
<input type="checkbox" v-model="item.purchased" >
<span>{{ item.purchased }}</span>
</li>
</ul>
</section>
</div>
<script>
Vue.createApp({
data() {
return{
title: '零食清单',
food: [
{id: 1, name: '原味鱿鱼丝', purchased: false },
{id: 2, name: '辣味鱿鱼丝', purchased: false },
{id: 3, name: '碳味鱿鱼丝', purchased: false },
]
}
}
}).mount('#app');
</script>
</body>
</html>

v-for 中的key

v-for 中以key作为数组中元素的唯一标识。这个key默认为index

v-for=“(item,index) in items” 这里的index就是默认的key

如果和当前示例代码一样,一个数组要被两个v-for使用过滤器过滤后当作参数时,就可能使vue犯迷糊。

这时就应该让key绑定这个数组的唯一标识。

如这里让key=id

1
<li v-for="item in foods.filter(item => item.purchased)" bind:key="item.id" ></li>

注意:这里的 bind:key= 可以缩写为 :key=(vue的常用简化写法)

v-show

vue中控制dom中某个元素显示与不显示的属性

底层:利用css中的display进行控制控制

本例中section标签就使用了v-show属性。

1
<section v-show="food.filter(item => item.purchased).length"></section>

元素中v-show属性的值为true就会显示

filter过滤器接下来讲

filter 过滤器

作用:过滤,选出自己想要的目标

本例在循环和v-show里均使用了filter

以循环中的filter为例

1
<li v-for="item in food.filter( item => item.purchased )"></li>

这里的filter筛选出了food数组中满足(item.purchased)的值大于0的元素

computed() 计算属性

以上这个例子有许多重复的地方

如:food.filter( item => item.purchased ) 和 food.filter( item => ! item.puchased )

这种重复的东西可以放进计算属性里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Vue.createApp({
data() {
return{
title: '零食清单',
food: [
{id: 1, name: '原味鱿鱼丝', purchased: false },
{id: 2, name: '辣味鱿鱼丝', purchased: false },
{id: 3, name: '碳味鱿鱼丝', purchased: false },
]
}
},
computed: {
beforeBuy() {
return this.food.filter( item => !item.purchased );
},
afterBuy() {
return this.food.filter( item => item.purchased );
}
}
}).mount('#app');

然后,html中换成计算属性中的函数名就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div id="app">
<h1>{{ title }}</h1>
<section v-show="beforeBuy">
<h1>未购买</h1>
<ul>
<li v-for="item in beforeBuy" :key="item.id">
<span>{{ item.name }}</span>
<input type="checkbox" v-model="item.purchased" >
<span>{{ item.purchased }}</span>
</li>
</ul>
</section>
<section v-show="afterBuy">
<h1>已购买</h1>
<ul>
<li v-for="item in afterBuy" :key="item.id">
<span>{{ item.name }}</span>
<input type="checkbox" v-model="item.purchased" >
<span>{{ item.purchased }}</span>
</li>
</ul>
</section>
</div>

组件、拆组件和引用组件

先来看一下createApp方法的本体

1
Vue.createApp({data(){},computed:{},template})

了解了data()函数、computed属性之后,还有一个template属性。

template:模板

简单来说,template里就是用来放html的

因为vue会把实例挂载到dom节点上,所以不用在dom节点内写html。

可以直接在template上写html,然后把内容挂到dom上。

这时候,就不用多次书写html,而是用vue一对多地挂载上去。

而当挂在的内容越来越多,页面就会越来越乱。这时候就需要引出vue的一个概念——组件。

创建和使用组件的步骤如下

1、在项目目录创建一个名为components的文件夹

这个文件夹用来存放接下来创建的组件

2、在components文件夹中新建一个App.js文件用来存放组件

  • 一个组件就是一个文件

  • 单文件组件

3、App.js 需要使用export语句导出为一个组件对象,便于在其他地方import引入

1
2
3
4
5
6
export default{
template: ``,
data() {},
computed: {}
...
}

4、在html中引入根组件:

1
2
3
4
<script type="module">
import App from './components/App.js';
Vue.createApp(App).mount('#app');
</script>

将引入的对象App作为参数,传入createApp()方法中,此时vue会根据App创建一个实例,并挂载到dom中

5、在组件中引入组件

1
2
3
4
5
6
7
import AppSections from "./AppSection.js"
export default {
components: { AppSections },
template: /*html*/`
<app-sections></app-sections>
`
}
  • 要在组件中引入一个AppSection组件作为子组件,首先需要导入AppSection。

随后按照惯例,写好导出部分export{…},然后再在里面的cmponents属性里写上import的组件实例名,最后在template属性(模板属性)里自定义的位置加上组件的对应标签(如第5行,下面会讲)。

  • components是一个和data()、computed、template同级的属性,作用是接收一个组件对象。

  • 如第3行,这里的componets属性接收了一个AppSections对象。

  • 如第5行,这是将引入的组件嵌入到本组件的方法。组件和标签的名字是一一对应的。若组件名为 AAA ,那么标签名就是

注意:html默认不区分大小写,所以尤大大不采用驼峰命名法作为标签名

所以:形如“AppSection”对应的标签名为

6、props传值

prop属性写在子组件里,用来接收父组件传入的值。

props和template、data()、computed是同级的属性

也就是说:

1
Vue.createApp(components:{},template:``,computed:{},props{})

以下是一个使用了props的组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
export default {
template: /*html*/`
<section v-show="buylist.length">
<h2>{{ headline }}</h2>
<ul>
<li v-for="len in buylist" :key="len.id">
<h5>
<input type="checkbox" v-model="len.purchased">
{{len.id}} {{len.name}} prices: {{len.prices}}
</h5>
</li>
</ul>
</section>
`,
props: {
headline: String,
buylist: Object
}

}

props的写法如15-18行。需要注意的是props大括号里元素的值应该是元素的类型。既然表示类型,那么必须要记住首字母大写

在子组件中 props的元素用插值表达式或数据绑定的形式将props的值插入到template模板中。

父组件运用含props传值组件的写法如下:

1
2
3
4
5
template: /*html*/`
<list-child headline="未购买" :buylist="filters.beforeBuy"></list-child>

<list-child headline="已购买" :buylist="filters.afterBuy"></list-child>
`,

标签中添加名字与子组件中props元素同名的属性。记得使用数据绑定。


v-on、methods、v-if、style和class绑定

v-on 监听事件

我们可以在需要监听的元素上添加v-on,然后用冒号接上事件的名字

1
<button v-on:click=" "></button>

像 v-bind 一样 这种常用的东西都会有缩写——@

1
<button @:click=" "></button>

methods 属性

里面放可以调用的方法,和computed等同级的一个属性。

也就是说

1
Vue.createApp(template,data(),computed,props,methods)

methods写法格式的一个例子:

1
2
3
4
5
6
7
8
9
10
methods: {
add() {
this.lens.push({
id: this.lens.length + 1,
name: '',
prices: '',
purchased: false
})
}
}

v-on 配合 methods属性使用

例:

在template属性中:

1
2
3
4
<form v-on:submit="add">
<input type="text" placeholder="输入想买的镜头...">
<button type="submit">添加</button>
</form>

methods属性:

1
2
3
4
5
6
7
8
9
10
methods: {
add() {
this.lens.push({
id: this.lens.length + 1,
name: '',
prices: '',
purchased: false
})
}
}

然而这样点击了form中的按钮后,网页会默认刷新 导致lens数组里面没有添加东西

.prevent 事件修饰符

prevent ——-等于javascript的event.preventDefault () 作用:阻止默认程序的运行

[(23条消息) vue-事件修饰符-详解(.prevent .stop .once .capture .self)_Ace-Liang的博客-CSDN博客](https://blog.csdn.net/weixin_43873005/article/details/89501985#:~:text=vue-事件修饰符-详解(.prevent .stop .once .capture .self) 1 .prevent ——-等于javascript的event.preventDefault,但是不会阻止冒泡 ! … 5 .once 顾名思义, 事件只会触发一次 )

这里的作用:

1
2
3
4
<form v-on:submit.prevent="add">
<input type="text" placeholder="输入想买的镜头...">
<button type="submit">添加</button>
</form>

第一行在 v-on:submit后面加上了.prevent 阻止了默认的刷新

v-if、v-else-if、v-else

和 if、else if、else一样,起到一个分支语句的作用

和 if( ) 一样 判断传入的值是 true 或 false,true就显示元素,false就跳到下一个条件

1
2
3
<button v-if="lens.length <= 3" type="submit">添加</button>
<button v-else-if="lens.length > 3 && lens.length <=5" type="submit">再加</button>
<button v-else="lens.length > 5" type="submit">狠狠加</button>

$emit()方法

作用:向父组件暴露本组件内触发的事件

1
2
3
4
votefor() {
this.count = this.count + 1;
this.$emit('votefor', this.item.name);
}

此时,当子组件内触发votefor() 方法时,父组件也能监听到这个方法。

若父组件使用v-on监听子组件暴露的事件,如:

1
<vote-item :item="item" @votefor="voteRecord"></vote-item>

那么,父组件在监听到子组件votefor事件时,会调用自己的voteRecord方法。

此时,子组件$emit()方法内的第二个参数将成为参数传入到父组件所调用方法内作为参数。如:

1
2
3
voteRecord(name) {
this.records.unshift({name: name, time: new Date().toLocaleString()});
}

注意:父组件的voteRecord()方法是一个有参数的方法,参数为name。那么子组件传递过来的“this.item.name”将传入父组件方法中的“name”。

vue路由

vue-router没有被集成到vue.js内。

所以,要使用vue路由,需要在项目文件夹中执行npm命令安装vue路由:

1
npm install vue-router@4

引入createRouter函数

在main.js文件中引入createRouter函数(第2行):

1
2
3
4
5
6
7
import { createApp } from 'vue'
import { createRouter } from 'vue-router'
import './style.css'
import App from './App.vue'

createApp(App).mount('#app')

createRouter:字面意思就是创建路由

你可以发现createRouter和createApp函数如此相似,因此这个函数也是创建一个对象,对象里会有属性。

为方便后续使用,创建一个变量router来保存路由实例。

routes属性

routes是路由对象里的一个属性,属性值接收一个数组

1
2
3
4
5
const router = createRouter(
{
routes: []
}
)

history属性

history属性用于存放历史规则(第3行)

1
2
3
4
5
6
7
8
9
10
11
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter(
{
history: createWebHistory(),
routes: [
{path: '/', component: Home },
{path: '/chicken-egg', component: ChickenEgg }
]
}
)

一个简单的使用vue路由的例子

在main.js中

  1. 引入路由和历史规则(2)

  2. 然后在下方创建一个常量 router 存放 createRouter()函数创建的路由对象。(8)

  3. 填充对象的属性。(10-11)

  4. 在createApp函数调用时,要使用use()方法,定义根组件所使用的路由。(18)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import './style.css'
import App from './App.vue'
import Home from './views/Home.vue'
import ChickenEgg from './views/ChickenEgg.vue'

const router = createRouter(
{
history: createWebHistory(),
routes: [
{path: '/', component: Home },
{path: '/chicken-egg', component: ChickenEgg }
]
}
)

createApp(App).use(router).mount('#app')

注意:routes数组中,component键的值已经在4-5行导入。

在App.js中

  1. 直接在template里塞入一个的标签
1
2
3
<template>
<router-view></router-view>
</template>

大功告成。

使用a标签/router-view标签进行页面组件的切换跳转

前面已经简单实现了vue路由。

简单来说,vue路由的作用就是把不同的组件与网站中不同的路径相关联,当输入某个url路径时,页面位置会切换到对应的组件。

使用进行页面切换的两种途径:

  1. a标签(3-4)
  2. router-link标签(5-6)
1
2
3
4
5
6
7
8
9
10
<!-- 在App.vue中 -->
<template>
<nav>
<a href="/">主页</a> |
<a href="/chicken-egg">鸡蛋</a> |
<router-link to='/'>主页</router-link> |
<router-link to='/chicken-egg'>鸡蛋</router-link>
</nav>
<router-view></router-view>
</template>

两种方法都可行,但是使用router-link标签将不会导致页面刷新。(高效)

使用router-link标签时,需要注意到其中的to属性

这里的to属性对应的就是显示当前数据时地址栏的url内容。