Vue 是一套用来动态构建用户界面的渐进式JavaScript前端框架
作者:尤雨
MVVM 是 vue 实现数据驱动视图和双向数据绑定的核心原理。
MVVM 指的是 Model、View 和 ViewModel, 它把每个 HTML 页面都拆分成了这三个部分,如图所示:
在 MVVM 概念中:
Model 表示当前页面渲染时所依赖的数据源。
View 表示当前页面所渲染的 DOM 结构。
ViewModel 表示 vue 的实例,它是 MVVM 的核心
MVVM 的工作原理 :ViewModel 作为 MVVM 的核心,是它把当前页面的数据源(Model)和页面的结构(View)连接在了一起。
当数据源发生变化时,会被 ViewModel 监听到,VM 会根据最新的数据源自动更新页面的结构,当表单元素的值发生变化时,也会被 VM 监听到,VM 会把 变化 过后最新的值自动同步到 Model 数据源中
编码简洁,体积小,运行效率高,适合移动/PC端开发
它本身只关注 UI,可以引入其它第三方库开发项目
采用组件化模式,提高代码复用率、且让代码更好维护
声明式编码,让编码人员无需直接操作DOM,提高开发效率
●使用****虚拟DOM****和 ****Diff算法****,尽量复用DOM节点
vue-cli:vue 脚手架
vue-resource(axios):ajax 请求
vue-router:路由
vuex:状态管理(它是 vue 的插件但是没有用 vue-xxx 的命名规则)
vue-lazyload:图片懒加载
vue-scroller:页面滑动相关
mint-ui:基于 vue 的 UI 组件库(移动端)
element-ui:基于 vue 的 UI 组件库(PC 端)
vue 框架的特性,主要体现在如下两方面:
数据驱动视图:
在使用了 vue 的页面中,vue 会监听数据的变化,从而自动重新渲染页面的结构。示意图如下:
好处:当页面数据发生变化时,页面会自动重新渲染!
注意:数据驱动视图是单向的数据绑定。
双向数据绑定:
在填写表单时,双向数据绑定可以辅助开发者在不操作 DOM 的前提下,自动把用户填写的内容同步到数据源 中。示意图如下:
好处:开发者不再需要手动操作 DOM 元素,来获取表单元素最新的值!
当前,vue 共有 3 个大版本,其中:
3.x 版本的 vue 于 2020-09-19 发布,生态还不完善,尚未在企业级项目开发中普及和推广
2.x 版本的 vue 是目前企业级项目开发中的主流版本
1.x 版本的 vue 几乎被淘汰,不再建议学习与使用
总结:
3.x 版本的 vue 是未来企业级项目开发的趋势;
2.x 版本的 vue 在未来(1 ~ 2年内)会被逐渐淘汰;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>我的第一个Vue程序</title>
</head>
<body>
</body>
</html>
方式一:
直接下载本地.js文件:网页链接
放入当前项目的js目录下:
方式二:
直接导入:
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>我的第一个Vue程序</title>
<script src="js/vue.js"></script>
</head>
<body>
<h1 id="h1">{{message}}</h1>
</body>
<script>
let vm = new Vue({
el: "h1",
data: {
message: "hello,Vue~"
}
});
</script>
</html>
<body>
<div id="app">
<h1 v-if="message">Ture</h1>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
message: false
}
});
</script>
let vm = new Vue({
el: "#app",
data: {
message: false
}
});
和基本的if 语句一样当数据为false的时候,就不执行当前语句:
<body>
<div id="app">
<h1 v-if="message">Ture</h1>
<h1 v-else="message">False</h1>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
message: false
}
});
</script>
<body>
<div id="app">
<h1 v-if="score >= 90">90以上</h1>
<h1 v-else-if="score >= 80">80以上</h1>
<h1 v-else-if="score >= 70">70以上</h1>
<h1 v-else-if="score >= 60">60以上</h1>
<h1 v-else>60以下</h1>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
score: 92
}
});
</script>
<body>
<div id="app">
<p v-for="user in userList">
用户名: {{user.username}}, 密码: {{user.password}} <br />
</p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
userList: [
{username: "怀旧1", password: "123456"},
{username: "怀旧2", password: "123456"},
{username: "怀旧3", password: "123456"}
]
}
});
</script>
扩展:遍历出每一个index:
<body>
<div id="app">
<p v-for="(user, index) in userList">
{{index + 1}}、用户名: {{user.username}}, 密码: {{user.password}} <br />
</p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
userList: [
{username: "怀旧1", password: "123456"},
{username: "怀旧2", password: "123456"},
{username: "怀旧3", password: "123456"}
]
}
});
</script>
迭代出来的下标,默认重0开始
绑定事件,首先需要定义一个方法来触发事件:
<body>
<div id="app">
<button v-on:click="hello">点击</button>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "你好"
},
methods: {
hello: function (){
alert(this.message);
}
}
});
</script>
点击按钮,触发事件!
<body>
<div id="app">
<input type="text" v-model="message" /> {{message}}
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
message: ""
},
});
</script>
测试单选框值获取
<body>
<div id="app">
性别:
<input type="radio" value="男" name="sex" v-model="checked" /> 男
<input type="radio" value="女" name="sex" v-model="checked" /> 女
<p>{{checked}}</p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
checked: ""
},
});
</script>
下拉框测试:
默认选中下拉框
<body>
<div id="app">
地址:
<select v-model="selected">
<option disabled>---请选择---</option>
<option value="重庆">重庆</option>
<option value="四川">四川</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
</select>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
selected: "上海"
},
});
</script>
测试选中状态获取值
<body>
<div id="app">
地址:
<select v-model="selected">
<option disabled>---请选择---</option>
<option value="重庆">重庆</option>
<option value="四川">四川</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
</select>
<p>{{selected}}</p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
selected: "---请选择---"
},
});
</script>
自定义模版,实现代码复用!
<body>
<div id="app">
<hj v-for="itemUser in users" v-bind:user="itemUser"></hj>
</div>
</body>
<script>
Vue.component("hj", {
props: ['user'],
template: "<li>{{user}}</li>"
});
let vm = new Vue({
el: "#app",
data: {
users: ["怀旧1", "怀旧2", "怀旧3"]
}
});
</script>
方式一:下载地址:点击访问
方式二:
<script src="https://unpkg.com/axios@1.6.8/dist/axios.min.js"></script>
<body>
<div id="app"></div>
</body>
<script>
let vm = new Vue({
el: "#app",
mounted(){
axios.get("test.json").then(response => (
console.log(response.data)
))
}
});
</script>
<body>
<div id="app">
<p>username: {{reData.username}}</p>
<p>password: {{reData.password}}</p>
<p><a v-bind:href="reData.huaijiuwang.url">点击访问怀旧网</a></p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data(){
return{
reData: {
username: null,
password: null,
huaijiuwang: {
url: null
}
}
}
},
mounted(){
axios.get("test.json").then(response => (
this.reData = response.data
))
}
});
</script>
点击链接测试:
测试原始方法:
<body>
<div id="app">
<p>time1: {{getTime1()}}</p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
methods: {
getTime1: function (){
return Date.now();
}
}
});
</script>
修改代码:
去掉调用发发的括号:
测试计算属性:
<body>
<div id="app">
<p>time1: {{getTime1()}}</p>
<p>time2: {{getTime2}}</p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
methods: {
getTime1: function (){
return Date.now();
}
},
computed: {
getTime2: function (){
return Date.now();
}
}
});
</script>
通过测试可以看出计算属性的调用方式是直接通过属性的形式调用,当使用方法调用会报错!
然后就是计算属性的值,一直都没有发生改变(因为计算属性默认有缓存),但是方法的值就会每次调用都改变!
测试让缓存刷新:
<script>
let vm = new Vue({
el: "#app",
data: {
test: "aa"
},
methods: {
getTime1: function (){
return Date.now();
}
},
computed: {
getTime2: function (){
this.test;
return Date.now();
}
}
});
</script>
通过测试可以看出当计算属性中的某个值发生改变的时候,就会刷新缓存!
官网教学:网页链接
测试代码:
<body>
<div id="app">
<slot-test>
<test-title slot="test-title" :title="title"></test-title>
<test-li slot="test-li" v-for="user1 in userList" :user="user1"></test-li>
</slot-test>
</div>
</body>
<script>
Vue.component("slot-test", {
template: '<div>\
<slot name="test-title"></slot>\
<ul>\
<slot name="test-li"></slot>\
</ul>\
</div>'
});
Vue.component("test-title", {
props: ['title'],
template: '<p>{{title}}</p>'
});
Vue.component("test-li", {
props: ['user'],
template: "<li>{{user}}</li>"
});
let vm = new Vue({
el: "#app",
data: {
title: "用户列表",
userList: ["怀旧1", "怀旧2", "怀旧3"]
}
});
</script>
代码:
<body>
<div id="app">
<slot-test>
<test-title slot="test-title" :title="title"></test-title>
<test-li slot="test-li" v-for="(user1, index) in userList" :user="user1" @remove="removeData(index)" ></test-li>
</slot-test>
</div>
</body>
<script>
Vue.component("slot-test", {
template: '<div>\
<slot name="test-title"></slot>\
<ul>\
<slot name="test-li"></slot>\
</ul>\
</div>',
});
Vue.component("test-title", {
props: ['title'],
template: '<p>{{title}}</p>'
});
Vue.component("test-li", {
props: ['user'],
template: "<li>{{user}}--<button @click='remove'>删除</button></li>",
methods: {
remove: function (){
this.$emit("remove");
}
}
});
let vm = new Vue({
el: "#app",
data: {
title: "用户列表",
userList: ["怀旧1", "怀旧2", "怀旧3"]
},
methods: {
removeData: function (index){
this.userList.splice(index, 1);
}
}
});
</script>
点击怀旧2后面的删除
直接官网下载:网页链接
安装完成测试:
安装 Node.js 淘宝镜像加速器 (cnpm)--提升下载速度
直接运行下面代码(安装速度可能比较慢);
npm install cnpm -g
第二种方式:
在每次下载的时候加入如下的命令,也可以提升速度(比较麻烦,每次都需要写):
npm install --registry=https://registry.npm.taobao.org
直接运行代码:
cnpm install -g @vue/cli
测试是否安装成功:
vue -V
创建一个vue-cli的项目:
npm create vue@latest
查看目录创建成功!
npm install
执行完毕,就可以开始运行项目了!
npm run dev
启动完成,访问 http://localhost:5173/
出现界面,说明运行成功!
详细内容访问:网页链接
执行如下命令:
npm install vue-router@4
安装完成:
在src目录下创建一个router目录,里面创建一个index.js文件
// 引入
import {createRouter, createWebHistory} from 'vue-router'
const routes = [
]
// 创建路由
const router = createRouter({
history: createWebHistory(),
routes: routes
})
// 导出路由
export default router
Hello1.vue
<template>
<h1>Hello1</h1>
</template>
<script>
export default {
name: "Hello1"
}
</script>
<style scoped>
</style>
Hello2.vue
<template>
<h1>Hello2</h1>
</template>
<script>
export default {
name: "Hello2"
}
</script>
<style scoped>
</style>
// 引入
import {createRouter, createWebHistory} from 'vue-router'
import Hello1 from "../components/Hello1.vue";
import Hello2 from "../components/Hello2.vue";
const routes = [
{
path: "/hello1",
component: Hello1
},
{
path: "/hello2",
component: Hello2
}
]
// 创建路由
const router = createRouter({
history: createWebHistory(),
routes: routes
})
// 导出路由
export default router
5.1、导入路由的配置+配置路由
import './assets/main.css';
import { createApp } from 'vue';
import App from './App.vue';
import rou from "./router";
const app = createApp(App);
app.use(rou);
app.mount('#app');
5.2、编写测试
<script setup>
</script>
<template>
<router-link to="/hello1">hello1</router-link>
<router-link to="/hello2">hello2</router-link>
<router-view></router-view>
</template>
<style scoped>
</style>
点击Hello1
点击Hello2
Element UI 官网: 网页链接
安装需要的组件 install 可以缩写为 i
npm i element-plus --save
安装 SASS 加载器(可以不装)
cnpm install sass-loader node-sass --save-dev
使用测试:
创建一个TestElement.vue (里面的数据直接去官网粘贴一个)
<template>
<el-time-select
v-model="value"
:picker-options="{
start: '08:30',
step: '00:15',
end: '18:30'
}"
placeholder="选择时间">
</el-time-select>
</template>
<script>
export default {
data() {
return {
value: ''
};
}
}
</script>
<style scoped>
</style>
注册界面到路由中:
{
path: "/testElement",
component: TestElement
}
导入element-plus配置
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import elementUI from "element-plus"
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(router)
app.use(elementUI)
app.mount('#app')
编写测试界面:
<script setup>
</script>
<template>
<router-link to="/testElement">testElement</router-link>
<router-view></router-view>
</template>
<style scoped>
</style>
测试运行:
点击:
换一个组件试试:
<template>
<div class="demo-progress">
<el-progress :text-inside="true" :stroke-width="26" :percentage="70" />
<el-progress
:text-inside="true"
:stroke-width="24"
:percentage="100"
status="success"
/>
<el-progress
:text-inside="true"
:stroke-width="22"
:percentage="80"
status="warning"
/>
<el-progress
:text-inside="true"
:stroke-width="20"
:percentage="50"
status="exception"
/>
</div>
</template>
<script>
export default {
data() {
return {
value: ''
};
}
}
</script>
<style scoped>
.demo-progress .el-progress--line {
margin-bottom: 15px;
max-width: 600px;
}
</style>
运行效果:
默认情况:
访问有数据的界面,没问题:
测试访问不存在的路径:
同样没有报错,这种情况我们就可以添加一个路由!
先创建一个显示404的vue界面
<template>
<h1>404~~~~~~~</h1>
</template>
<script>
</script>
<style scoped>
</style>
配置路由:
import { createRouter, createWebHistory } from 'vue-router'
import TestElement from "../components/TestElement.vue"
import error from "../components/error.vue"
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/testElement",
component: TestElement
},
{
path: '/:pathMatch(.*)',
component: error,
hidden: true
}
]
})
export default router
访问存在路径:
没问题!
测试访问不存在路径:
直接跳转到404界面!
axios 官网:网页链接
直接在当前目录下执行命令:
npm install --save axios vue-axios
注册 axios 组件
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
编写一个vue界面 TestAxios.vue
<template>
<h1>测试Axios</h1>
</template>
<script>
</script>
<style scoped>
</style>
将界面绑定到路由:
import { createRouter, createWebHistory } from 'vue-router'
import TestAxios from "../components/TestAxios.vue"
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/testAxios",
component: TestAxios
}
]
})
export default router
配置:
beforeRouteEnter 路由执行前,执行特定方法(例如:查询数据)
beforeRouteLeave 路由执行后,执行特定方法(例如:查询数据)
参数介绍:
在界面配置两个拦截:
<template>
<h1>测试Axios</h1>
</template>
<script>
export default {
beforeRouteEnter: (to, from, next) => {
console.log("路由跳转前!");
next();
}
}
</script>
<style scoped>
</style>
运行测试:
配置测试在方法调用前,获取后端数据:
<template>
<div>
<P>username: {{reData.username}}</P>
<P>password: {{reData.password}}</P>
<P>url: <a :href="reData.huaijiuwang.url">网页链接</a></P>
</div>
</template>
<script>
export default {
beforeRouteEnter: (to, from, next) => {
// 方法执行中获取数据
next(vm => {
// 调用 vm 调用查询数据的方法
vm.getData();
});
},
data(){
return {
reData: {
username: null,
password: null,
huaijiuwang: {
url: null
}
}
}
},
methods: {
getData: function (){
let userData = {
username: "怀旧",
password: "123456",
huaijiuwang: {
url: "https://www.huaijiuwang.com.cn/"
}
}
this.reData = userData;
}
}
}
</script>
<style scoped>
</style>
访问测试:
创建一个json文件
测试访问这个json文件:
访问路径: http://localhost/src/assets/test.json
修改 TestAxios.vue 文件, 将获取数据的接口替换为 axios 请求
methods: {
getData: function (){
this.axios.get("http://localhost/src/assets/test.json").then(response => (
this.reData = response.data
))
}
}
// 另一种写法
methods: {
getData: function (){
this.axios({
method: 'get',
url: 'http://localhost/src/assets/test.json'
}).then(response => (
this.reData = response.data
))
}
}
测试运行:
获取数据成功!
评论
登录后才可以进行评论哦!