vue-element-template实战

一大坨东西

先复习一下vue

虚拟DOM 节省资源

声明式渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<!-- 鼠标悬浮看 title 属性 -->
<!--v-bind v-on-->
<div :title="msg" :click="handleClick" @click="handleClick">{{ msg }}</div>
</template>
<script>
export default {
name: "App",
data() {
return {
msg: "hello 蓝桥",
};
},
methods: {
handleClick(event) {
alert(event.target.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
35
36
37
38
39
40
41
42
43
<template>
<!-- <img alt="Vue logo" src="./assets/logo.png"> -->
<!-- <HelloWorld msg="Welcome to Your Vue.js App"/> -->
<div v-if="seen" v-bind:title="msg" @click="handleClick">{{msg}}</div>
<template v-for="todo in todos" :key="todo">
<div>{{ todo }}</div>
</template>
</template>

<script>
// import HelloWorld from './components/HelloWorld.vue'

export default {
name: 'App',
components: {
// HelloWorld
},
data(){
return {
msg:"Hello 蓝桥",
seen:true,
todos:["Vue", "React", "Angular"]
}
},
methods:{
handleClick() {
// alert(event.target.title);
this.seen = false
},
},
}
</script>

<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

组件化应用构建

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用.

简单来说,一个Vue文件就是一个组件,里面有template script style.

建立一个Vue文件,比如叫main-component.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
<template>
<!-- 鼠标悬浮看 title 属性 -->
<div v-if="seen" :title="msg" v-on:click="handleClick">
{{ msg }}
<!-- 循环渲染列表数据 -->
<template v-for="todo in todos" :key="todo">
<div>{{ todo }}</div>
</template>
</div>
</template>

<script>
export default {
name: "MainConcepts", // 组件名称
data() {
return {
msg: "hello 蓝桥",
seen: true, // 控制是否显示
todos: ["Vue", "React", "Angular"],
};
},
methods: {
handleClick() {
// alert(event.target.title);
this.seen = false;
},
},
};
</script>
<style></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<!-- 渲染 MainConcepts 组件-->
<main-concepts />
</template>

<script>
import MainConcepts from "./main-concepts"; // 引入 MainConcepts 组件
export default {
name: "App",
components: {
MainConcepts,
},
};
</script>
<style></style>

在 Vue 中,组件分为:“普通组件”、“函数式组件”、“类组件”。

Props代表了根组件的属性值

1
2
3
4
5
6
7
8
9
10
<template>
<!-- 声明式渲染 msg 数据 -->
<div>{{ msg }}</div>
</template>
<script>
export default {
name: "App",
props: ["msg"], // 给 App 组件定义一个 msg 属性
};
</script>
1
2
3
4
import { createApp } from "vue";
import App from "./App";
// 传递根组件,并传递根组件属性
createApp(App, { msg: "我是根组件属性中的 msg" }).mount("#app");
1
2
3
4
5
6
7
const app = Vue.createApp(...)
// 注册一个全局组件 SearchInput
app.component('SearchInput', SearchInputComponent)
// 注册一个全局指令 focus
app.directive('focus', FocusDirective)
// 插件的使用
app.use(LocalePlugin)

模板语法

1
<span>hello: {{ msg }}</span>
1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<span>hello: {{ msg }}</span>
</template>
<script>
export default {
name: "App",
data() {
return {
msg: "蓝桥",
};
},
};
</script>

指令

v-bind 指令给元素绑定了一个属性

用过v-if 条件指令去控制某个元素的显示,用过 v-on 指令绑定过 click 事件,用过 v-for 指令去循环渲染

1
2
3
4
5
6
7
<!-- 鼠标悬浮看 title 属性 -->
<div
v-if="seen"
:title="msg"
v-on:click="handleClick"
>
...

修饰符

修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()

1
<a v-on:click.prevent="handleLinkClick">...</a>
1
2
3
4
5
6
7
8
9
<template>
<a
v-bind:[attributeName]="msg"
v-on:[eventName].prevent="handleClick"
href="https://www.lanqiao.cn/courses"
>
{{ "hello" + msg }}
</a>
</template>

data属性

组件的 Data 属性是一个函数。Vue 在创建新组件实例的过程中调用此函数。它应该返回一个对象,然后 Vue 会通过响应性系统将其包裹起来,并以 $data 的形式存储在组件实例中。可以直接通过组件实例访问 $data 对象中的属性。

组件外可以通过组件实例来访问组件 Data 属性

1
2
3
4
5
6
7
8
9
10
import { createApp } from "vue";
import App from "./App.vue";
// 创建 app 应用实例
const app = createApp(App);
// 获取 App 根组件实例
const rootComponent = app.mount("#app");
console.log("App 组件中的 Data 属性:", rootComponent.$data);
console.log("App 组件中的 msg 数据:", rootComponent.msg);
// 修改组件的响应式数据 msg
rootComponent.msg = "我是 msg 数据,我在组件外被修改了";

在定义 methods 时应避免使用箭头函数,因为这会阻止 Vue 绑定恰当的 this 指向。

计算属性

计算属性可以依赖多个 Vue 实例的数据,只要其中任一数据变化,计算属性就会重新执行,视图也会更新。

计算属性 computed 在使用时,一定要注意,函数里面的变量都会被监听,只要里面的某一个值变动,便会将整个函数执行一遍。

计算属性的setter与getter

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
<template>
<div>
<fieldset>
<legend>单价:</legend>
<input :value="price" @input="handlePriceInput" />
</fieldset>
<fieldset>
<legend>数量:</legend>
<input :value="count" @input="handleCountInput" />
</fieldset>
总价:{{ total }}
<div @click="handleTotal">私自修改一下 total</div>
</div>
</template>

<script>
export default {
name: "App",
data() {
return {
count: 0, // 数量
price: 0, // 单价
};
},
computed: {
// 计算属性声明
total: {
// 定义 total 计算属性
// getter
get() {
return parseInt(this.count) * parseFloat(this.price);
},
// setter
set(newValue) {
alert("不允许直接操作 total 的值,你计算的:" + newValue + "无效!");
},
},
},
methods: {
/**
处理单价输入
*/
handlePriceInput(event) {
this.price = event.target.value;
},
/**
处理数量输入
*/
handleCountInput(event) {
this.count = event.target.value;
},
/**
* 自定义处理 total
*/
handleTotal() {
this.total = 0;
},
},
};
</script>

监听器

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的

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
77
<template>
<div>
<fieldset>
<legend>单价:</legend>
<input :value="price" @input="handlePriceInput" />
</fieldset>
<fieldset>
<legend>数量:</legend>
<input :value="count" @input="handleCountInput" />
</fieldset>
总价:{{ total }}
<div @click="handleTotal">私自修改一下 total</div>
</div>
</template>

<script>
export default {
name: "App",
data() {
return {
count: 0, // 数量
price: 0, // 单价
};
},
computed: {
// 计算属性声明
total: {
// 定义 total 计算属性
// getter
get() {
return parseInt(this.count) * parseFloat(this.price);
},
// setter
set(newValue) {
alert("不允许直接操作 total 的值,你计算的:" + newValue + "无效!");
},
},
},
watch: {
// 侦听器声明
count(newCount, oldCount) {
// 定义一个侦听器,名称跟响应式数据 count 一致
// 商品数量必须 >= 0
if (Number.isNaN(parseFloat(newCount)) || parseFloat(newCount) < 0) {
this.count = oldCount;
}
},
price(newPrice, oldPrice) {
// 定义一个侦听器,名称跟响应式数据 price 一致
// 单价必须 >= 0
if (Number.isNaN(parseFloat(newPrice)) || parseFloat(newPrice) < 0) {
this.price = oldPrice;
}
},
},
methods: {
/**
处理单价输入
*/
handlePriceInput(event) {
this.price = event.target.value;
},
/**
处理数量输入
*/
handleCountInput(event) {
this.count = event.target.value;
},
/**
* 自定义处理 total
*/
handleTotal() {
this.total = 0;
},
},
};
</script>

除了可以在 watch 选项中执行条件判断外,我们甚至可以在里面进行异步请求,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的

计算属性与侦听器的区别:

名称特性
计算属性(computed)1. 计算一个或多个响应式数据的值。 2. 应用:简化模版语法中的变量计算。 3. 具有缓存性,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数。
侦听器(watch)1. 观察一个响应式数据变化。 2. 应用:监听响应式数据的变化,做对应逻辑处理。 3. 具有缓存性,页面重新渲染值不变化,监听方法不会执行。

Vue-router

Hash模式

hash 模式是用 createWebHashHistory() 创建的:

1
2
3
4
5
6
7
8
import { createRouter, createWebHashHistory } from "vue-router";

const router = createRouter({
history: createWebHashHistory(),
routes: [
//...
],
});

它在内部传递的实际 URL 之前使用了一个哈希字符(#)。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。不过,它在 SEO 中确实有不好的影响。如果你担心这个问题,可以使用 HTML5 模式

HTML5模式

1
2
3
4
5
6
7
8
import { createRouter, createWebHistory } from "vue-router";

const router = createRouter({
history: createWebHistory(),
routes: [
//...
],
});

Vue-element-template

直接先看一下文档

vue-element-admin 是一个后台前端解决方案,它基于 vueelement-ui实现。它使用了最新的前端技术栈,内置了 i18 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件

建议你可以把 vue-element-admin当做工具箱或者集成方案仓库,在 vue-admin-template 的基础上进行二次开发,想要什么功能或者组件就去 vue-element-admin 那里复制过来。

布局

layout

对应代码@/layout

vue-element-admin 中大部分页面都是基于这个 layout 的,除了个别页面如:login , 404, 401 等页面没有使用该layout。如果你想在一个项目中有多种不同的layout也是很方便的,只要在一级路由那里选择不同的layout组件就行

app-main

对应代码

@/layout/components/AppMain

这里在 app-main 外部包了一层 keep-alive 主要是为了缓存 <router-view> 的,配合页面的 tabs-view 标签导航使用,如不需要可自行去除

其中transition 定义了页面之间切换动画,可以根据自己的需求,自行修改转场动画。相关文档。默认提供了fadefade-transform两个转场动画,具体 css 实现见transition.scss。如果需要调整可在AppMain.vue中调整transitionname

路由和侧边栏

本项目侧边栏和路由是绑定在一起的,所以你只有在 @/router/index.js 下面配置对应的路由,侧边栏就能动态的生成了。大大减轻了手动重复编辑侧边栏的工作量。当然这样就需要在配置路由的时候遵循一些约定的规则

资料

vue-element-admin (gitee.io)

一篇文章说清 webpack、vite、vue-cli、create-vue 的区别 - 金色海洋(jyk) - 博客园 (cnblogs.com)

-------------本文结束感谢您的阅读-------------
感谢阅读.

欢迎关注我的其它发布渠道