
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性。其特点是综合了Angular(模块化)和React(虚拟DOM)的优点,虚拟DOM就是把DOM *** 作放到内存中执行。
与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
Vue是 MVVM 模式的实现者。
MVVM(Model-View-ViewModel)是一种软件架构设计模式,是一种简化用户界面的事件驱动编程方式。核心是ViewModel层,负责转换Model中的数据对象,让数据变得更容易管理和使用,其作用如下:
该层向上与视图层进行双向数据绑定向下与Model层通过接口请求进行数据交互好处:
低耦合:视图可以独立于Model变化和修改;
可复用:把视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑;
独立开发:开发人员可以专注于业务逻辑和数据的开发,设计人员专注于页面设计。
可测试:界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。
MVVM的组成部分:
MVVM框架已经把最脏最累的一块做好了,我们开发者只需要处理和维护ViewModel,更新数据视图就会自动得到相应更新,真正实现事件驱动编程。
View层展现的不是Model层的数据,而是ViewModel的数据,由ViewModel负责与Model层交互,这就完全解耦了View层和Model层,这个解耦是至关重要的,它是前后端分离方案实施的重要一环。
在MVVM架构中,是不允许数据和视图直接通信的,只能通过ViewModel来通信,Vue.js就是MVVM中的ViewModel层的实现者,它的核心就是实现了DOM监听与数据绑定。
第一个Vue程序CDN:
压缩版:
完整版:
<body>
<div id="app">
{{message}}
div>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js">script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "hello,vue!"
}
});
script>
body>
安装Vue插件
新建文件:Vue Component
带有前缀 v- 称为指令,表示Vue提供的特殊特性,它们会在渲染的DOM上应用特殊的响应式行为。
if判断
<body>
<div id="app">
<h1 v-if="type==='A'">Ah1>
<h1 v-else-if="type==='B'">Bh1>
<h1 v-else-if="type==='D'">Dh1>
<h1 v-else="type==='C'">Ch1>
div>
<script>
var vm = new Vue({
el: "#app",
data: {
type: 'A'
}
});
script>
body>
for循环
<body>
<div id="app">
<li v-for="(item, index) in items">
{{index}}: {{item.message}}
li>
div>
<script>
var vm = new Vue({
el: "#app",
data: {
items: [
{message: '前端'},
{message: '后端'},
{message: '测试'},
{message: '运维'}
]
}
});
script>
body>
绑定事件
方法必须定义在Vue的methods对象中。v-on:事件
<div id="app">
<button v-on:click="sayHi">click mebutton>
div>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js">script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "java工程师"
},
methods: {
sayHi: function () {
alert(this.message);
}
}
});
script>
双向数据绑定
当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。
我们可以用v-model指令在表单 、及元素上创建双向数据绑定。
输入框:
<div id="app">
输入的文本:<input type="text" v-model="message"> {{message}}
div>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "123"
},
});
script>
在输入框输入内容,后面也会跟着变化。
单选框:
<div id="app">
<input type="radio" name="sex" value="男" v-model="gender"> 男
<input type="radio" name="sex" value="女" v-model="gender"> 女
<p>
性别:{{gender}}
p>
div>
<script>
var vm = new Vue({
el: "#app",
data: {
gender: ""
}
});
script>
下拉框:
<div id="app">
下拉框:
<select v-model="selected">
<option value="" disabled>--请选择--option>
<option>Aoption>
<option>Boption>
<option>Coption>
select>
<span>value:{{selected}}span>
div>
<script>
var vm = new Vue({
el: "#app",
data: {
selected: ""
}
});
script>
注意:v-model会忽略所有表单的value、checked、selected 特性的初始值而总是将Vue实例的数据作为数据来源。你应该通过JavaScript在组件的data选项中声明初始值!
组件是可复用的Vue实例,说白了就是一组可以重复使用的模板。通常一个应用会以一颗嵌套的组件树的形式来组织:
<div id="app">
<qinjiang v-for="item in items" v-bind:qin="item">qinjiang>
div>
<script>
//定义一个Vue组件
Vue.component("qinjiang", {
props: ['qin'], //传递参数
template: '{{qin}}' //模板
})
var vm = new Vue({
el: "#app",
data: {
items: ["java","Linus","前端"]
}
});
script>
首先在component中定义了一个“qinjiang”组件,props是组件的参数,template是组件的模板。我们想用这个自定义组件遍历一些数据,则需要用 v-bind 绑定参数。
代表的就是组件,向里面添加指令去取数据。
v-bind::绑定一个值。
v-for="item in items":遍历Vue实例中定义的名为items的数组,并创建同等数量的组件。
v-bind:qin="item":将遍历的item项绑定到组件中 props 定义的名为 qin 属性上;= 号左边的 qin 为 props 定义的属性名,右边的为 item in items中遍历的item项的值。
Axios是一个开源的可以用在浏览器端和NodeJS的异步通信框架,它的主要作用就是实现AJAX异步通信。
因为Vue的边界很明确,就是为了处理DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互。
中文文档:http://www.axios-js.com
注意:浏览器要是ES6规范的,不然无法使用。
为什么要使用Axios:
由于Vue.js是一个视图层框架,并且作者严格遵守了SOC(关注度分离原则),所以Vue.js并不包含Ajax的通信功能,为了解决通信问题,作者单独开发了一个名为vue-resource的插件,不过在进入2.0版本以后停止了对该插件的维护并推荐了Axios框架。
少用JQuery,因为它 *** 作DOM太频繁!
第一个Axios应用程序
我们开发的接口大部分都是采用JSON格式,可以先在项目中模拟一段JSON数据,数据内容如下(data.json):
{
"name":"狂神说java",
"url": "http://baidu.com",
"page": "1",
"isNonProfit":"true",
"address": {
"street": "含光门",
"city":"陕西西安",
"country": "中国"
},
"links": [
{
"name": "B站",
"url": "https://www.bilibili.com/"
},
{
"name": "4399",
"url": "https://www.4399.com/"
},
{
"name": "百度",
"url": "https://www.baidu.com/"
}
]
}
<div id="vue">
<div>{{info.name}}div>
<div>{{info.address.street}}div>
<a v-bind:href="info.url">点我a>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js">script>
<script src="https://unpkg.com/axios/dist/axios.min.js">script>
<script>
var vm = new Vue({
el: "#vue",
data() {
return {
//请求的返回参数格式,必须和json字符串一样
info: {
name: null,
address: {
street: null,
city: null,
country: null
},
url: null
}
}
},
mounted() { //钩子函数,链式编程,ES6新特性
axios.get('../data.json').then(response=>(this.info=response.data));
}
});
script>
说明:
这里使用了v-bind将a:href的属性值与Vue实例中的数据进行绑定。使用Axios框架的get方法请求Ajax并自动将数据封装进了Vue市里的数据对象中我们在data中的数据结构必须要和ajax响应回来的数据格式匹配。
Vue生命周期
官方文档:https://cn.vuejs.org/v2/guide/instance.html#
Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载DOM、渲染–>更新–>渲染、卸载等一些列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
在Vue的整个生命周期中,它提供了一个系列的事件,可以让我们在事件触发时注册JS方法,可以让我们用自己注册的JS方法控制整个大局,在这些事件响应方法中的this直接指向的是Vue的实例。
Vue钩子函数:就是指在一个Vue实例从创建到销毁的过程自动执行的函数。
计算属性computed:这个属性有计算的能力,这里的计算是一个函数。简单点说,它就是一个能够将计算结果缓存起来的属性,可以想象为缓存!
<div id="app">
<p>currentTime1 {{currentTime1()}}p>
<p>currentTime2 {{currentTime2}}p>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js">script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "hello,kuangshen"
},
methods: {
currentTime1: function () {
return Date.now();
}
},
computed: { //计算属性:methods、computed方法名不能一样
currentTime2: function () {
this.message;
return Date.now();
}
}
});
script>
说明:
methods:定义方法,调用方法使用currentTime1(),需要带括号。computed:定义计算属性,调用属性使用currentTime2,不需要带括号;this.message是为了能够让currentTime2观察到数据变化而变化。如果方法中的值发生了变化,缓存就会刷新!可以在浏览器的控制台使用vm.message="123",改变数据的值,再查看currentTime2的值。
结论:调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这一点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销。
内容分发(插槽)在Vue.js中,我们使用元素作为承载分发内容的出口,可以应用在组合组件的场景中。
比如准备一个待办事项组件(todo),该组件由待办标题(todo-title)和待办内容(todo-items)组成,但这三个组件又是相互独立的。该如何实现呢?
第一步:定义一个待办事项的组件
<div id="app">
<todo>
todo>
div>
<script>
Vue.component("todo",{
template: '\
待办事项\
\
Java系列\
\
'
});
script>
第二步:我们需要让待办事项的标题和值实现动态绑定,我们需要留出一个插槽!
将上面代码留出一个插槽,即slot
Vue.component("todo",{
template: '<div>\
<slot name="todo-title">slot>\
<ul>\
<slot name="todo-items">slot>\
ul>\
div>'
});
定义一个名为todo-title的待办标题组件和todo-items的待办内容组件
Vue.component("todo-title",{
props: ['title'],
template: '{{title}}'
});
Vue.component("todo-items",{
props: ['item'],
template: '{{item}}'
});
第三步:实例化Vue并初始化数据
var vm = new Vue({
el: "#app",
data: {
title: "秦老师系列课程",
todoItems: ['狂神说Java','狂神说前端',"狂神说Linux"]
}
});
第四步:将这些值,通过插槽插入
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:title="title"></todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" v-bind:item="item"></todo-items>
</todo>
</div>
测试:
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:title="title"></todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" v-bind:item="item"></todo-items>
</todo>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script>
//slot:插槽
Vue.component("todo",{
template: '<div>\
<slot name="todo-title"></slot>\
<ul>\
<slot name="todo-items"></slot>\
</ul>\
</div>'
});
Vue.component("todo-title",{
props: ['title'],
template: '<div>{{title}}</div>'
});
Vue.component("todo-items",{
props: ['item'],
template: '<li>{{item}}</li>'
});
var vm = new Vue({
el: "#app",
data: {
title: "秦老师系列课程",
todoItems: ['狂神说Java','狂神说前端',"狂神说Linux"]
}
});
</script>
说明:我们的todo-title和todo-items组件分别被分发到了todo组件的todo-title和todo-items插槽中。
自定义事件通过以上代码不难发现,数据项在Vue的实例中,但删除 *** 作要在组件中完成,那么组件如何才能删除Vue实例中的数据呢?此时就涉及到参数传递和事件分发了,Vue为我们提供了自定义事件的功能很好的帮助我们解决了这个问题:使用 this.$emit('自定义事件名', 参数)
1. 在vue的实例中,增加了methods对象并定义了一个名为removeItems的方法
var vm = new Vue({
el: "#app",
data: {
title: "秦老师系列课程",
todoItems: ['狂神说Java','狂神说前端',"狂神说Linux"]
},
methods: {
removeItems:function (index) {
console.log("删除了" + this.todoItems[index] + "OK");
this.todoItems.splice(index,1);
}
}
});
2. 修改todo-tems待办内容组件的代码,增加一个删除按钮,并且绑定事件!
Vue.component("todo-items",{
props: ['item','index'],
// v-on绑定事件,简写@
template: '{{index}}--{{item}} ',
methods: {
remove: function (index) { //这个index是上面todo-items传递下来的index
//remove是自定义事件的名称,让remove和上面todo-items绑定起来,使用v-on:remove的方式
this.$emit('remove', index);
}
}
});
3. 修改todo-items待办内容组件的HTML代码,增加一个自定义事件,比如叫remove,可以和组件的方法绑定,然后绑定到vue的方法中!
<todo-items slot="todo-items" v-for="(item,index) in todoItems" v-bind:item="item" v-bind:index="index"
v-on:remove="removeItems(index)" v-bind:key="index">todo-items>
测试
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:title="title">todo-title>
<todo-items slot="todo-items" v-for="(item,index) in todoItems" v-bind:item="item" v-bind:index="index"
v-on:remove="removeItems(index)" v-bind:key="index">todo-items>
todo>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js">script>
<script>
//slot:插槽
Vue.component("todo",{
template: '\
\
\
\
\
'
});
Vue.component("todo-title",{
props: ['title'],
template: '{{title}}'
});
Vue.component("todo-items",{
props: ['item','index'],
// v-on绑定事件,简写@
template: '{{index}}--{{item}} ',
methods: {
remove: function (index) { //这个index是上面todo-items传递下来的index
//让remove和上面todo-items绑定起来,实现自定义分发
this.$emit('remove', index);
}
}
});
var vm = new Vue({
el: "#app",
data: {
title: "秦老师系列课程",
todoItems: ['狂神说Java','狂神说前端',"狂神说Linux"]
},
methods: {
removeItems:function (index) {
console.log("删除了" + this.todoItems[index] + "OK");
this.todoItems.splice(index,1); //删除当前下标元素。1代表删除1个,2代表删除当前和它后面的一个
}
}
});
script>
理解:
第一个vue-cli程序
Vue的开发都是要基于NodeJS,实际开发采用vue-cli脚手架开发,vue-router路由,vuex做状态管理;界面我们一般采用ElementUI,或者ICE来快速搭建前端项目。
vue-cli:官方提供的一个脚手架,用于快速生成一个vue项目模板。
主要功能:统一的目录结构、本地调试、热部署、单元测试、集成打包上线。
去官网下载node.js
cmd 下输入 node -v:查看是否能够正确打印出版本号
cmd 下输入 npm -v
安装Node.js淘宝镜像加速(cnpm)
# -g就是全局安装
npm install cnpm -g
安装 vue-cli
cnpm install vue-cli -g
# 测试是否安装成功
# 查看可以基于哪些模板创建vue应用程序,通常使用webpack
vue list
创建一个基于webpack模板的vue应用程序:
# 在想要创建项目的路径下,运行如下代码(myvue是项目名)
vue init webpack myvue
执行vue init webpack myvue后一直停在…downloading template的情况:
继续执行刚才的代码:
一路选择“no”
然后进入 myvue目录cd myvue,进行初始化并运行。
npm install
npm run dev
我npm install安装后,有很多警告,不知道是为什么。
访问:http://localhost:8080,可以进入node.js服务器,有点像启动tomcat。
WebPack是一款模块加载器兼打包工具,它能把各种资源,如JS、JSX、ES6、SASS、图片等都作为模块来处理和使用。
安装:
npm install webpack -g
npm install webpack-cli -g
配置
创建 webpack.config.js 配置文件
module.exports = {
entry: './modules/main.js',
output: {
filename: "./js/bundle.js"
}
};
使用webpack
创建项目,用idea打开。创建一个名为modules的目录,用于放置JS模块等资源文件。在modules下创建模块文件,如hello.js,用于编写JS模块相关代码。//暴露一个方法
exports.sayHi = function () {
document.write("狂神说ES6");
}
在modules下创建一个名为main.js的入口文件,用于打包时设置entry属性。var hello = require("./hello");
hello.sayHi();
在项目目录下创建webpack.config.js配置文件,使用webpack命令打包module.exports = {
entry: './modules/main.js',
output: {
filename: "./js/bundle.js"
}
};
打包完会生成一个文件
创建一个html文件,将打包好的这个js文件引入进去
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<script src="dist/js/bundle.js">script>
body>
html>
打开浏览器就会执行刚才写的方法如果在idea控制台执行webpack失败,用管理员权限运行即可! vue-route路由
Vue路由是指根据url分配到对应的处理程序;作用就是解析URL,调用对应的控制器(的方法,并传递参数)。
Vue路由有助于在浏览器的URL或历史记录与Vue组件之间建立链接,从而允许某些路径渲染与之关联的任何一个视图。
在web开发中,客户端的请求是以url的形式传递给服务器,它根据URL将请求分配到指定的一个端并且在这个过程中对其进行处理。然后路由再调用相关的控制器,控制器调用相关的服务,并返回视图对象。路由再从视图对象中提取生成好的网页代码返回给Web服务器,最终返回给客户端。
安装:
npm install vue-router --save-dev #当时安装报错了
npm install -g vue-router --save # 这个安装没报错,但是没安装下来
npm install --legacy-peer-deps vue-router@3.5.2 # 成功
如果在一个模块化工程中使用它,必须要通过Vue.use() 明确地安装路由功能:
import Vue from 'vue'
import VueRouter from 'vue-router'
//显示声明使用VueRouter
Vue.use(VueRouter);
测试:
1. components目录下存放我们自己编写的组件
2. 定义一个Content.vue和一个Main.vue
<template>
<h1>内容页</h1>
</template>
<script>
export default {
name: "Content"
}
</script>
<template>
<h1>首页</h1>
</template>
<script>
export default {
name: "Main"
}
</script>
3. 安装路由,在src目录下,新建一个文件夹:router,专门存放路由。router文件夹下新建一个index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Content from "../components/Content";
import Main from "../components/Main";
//安装路由
//显示声明使用VueRouter
Vue.use(VueRouter);
//配置导出路由
export default new VueRouter({ //这里VueRouter和上面导入的VueRouter名字要一致
routes: [
{
//路由路径
path: '/content',
name: 'content', //路由名字
//跳转的组件
component: Content
},
{
//路由路径
path: '/main',
name: 'content',
//跳转的组件
component: Main
}
]
});
4. 在main.js中配置路由
import Vue from 'vue'
import App from './App'
//自动扫描route下的路由配置,这个路由配置是index.js
import router from './router'
Vue.config.productionTip = false;
new Vue({
el: '#app',
//配置路由
router,
components: { App },
template: ''
});
5. 在App.vue中使用路由,点击可以跳转到相应的页面
<template>
<div id="app">
<h1>Vue-Router</h1>
<router-link to="/main">首页</router-link>
<router-link to="/content">内容页</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</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>
element-ui
创建工程
创建一个名为 hello-vue 的工程vue init webpack hello-vue安装依赖,我们需要安装 vue-router、element-ui、sass-loader和node-sass四个插件。# 进入工程目录
cd hello-vue
# 安装 vue-router
# npm install vue-router --save-dev
npm install --legacy-peer-deps vue-router@3.5.2
# 安装 element-ui
npm i element-ui -S
# 安装依赖
npm install
# 安装 SASS 加载器
cnpm install sass-loader node-sass --save-dev
# 启动测试
npm run dev
写两个视图:Login.vue、Main.vue(包括elementUI)路由import Vue from 'vue'
import Router from 'vue-router'
import Main from "../views/Main";
import Login from "../views/Login";
Vue.use(Router)
export default new Router({
routes:[
{
path: '/main',
component: Main
},
{
path: '/login',
component: Login
}
]
});
main.jsimport Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(router);
Vue.use(ElementUI);
new Vue({
el: '#app',
router,
render: h => h(App)
});
嵌套路由
嵌套路由又称子路由,在实际应用中,通常由多层嵌套的组件组合而成。同样的,URL中各段动态路径也按某种结构对应嵌套的各层组件,如:
import UserList from "../views/user/List"
import UserProfile from "../views/user/Profile"
Vue.use(Router)
export default new Router({
routes:[
{
path: '/main',
component: Main,
//嵌套路由
children: [
{path: '/user/profile', component:UserProfile},
{path: '/user/list', component:UserList}
]
},
{
path: '/login',
component: Login
}
]
});
参数传递及重定向
比如展示个人信息,要根据不同的对象展示不同的信息,这时就需要传递参数。
原来没有传递参数
<router-link :to="{name:'/user/profile', params:{id:1}}">个人信息</router-link>
name:传递给哪个路由
params:参数
children: [
{path: '/user/profile/:id', component:UserProfile},
{path: '/user/list', component:UserList}
]
<template>
<div>
<h1>用户信息</h1>
{{$route.params.id}}
</div>
</template>
重定向
routes:[
{
path: '/main',
component: Main,
children: [
{path: '/user/profile/:id', component:UserProfile},
{path: '/user/list', component:UserList}
]
},{
path: '/goHome',
redirect: '/main' //重定向
}
]
重定向到main页面
<router-link to="/goHome">回到首页</router-link>
404与路由钩子
路由模式有两种:
hash:路径带 # 符号
history:路径不带 # 符号
修改路由配置如下:
export default new Router({
mode: 'history',
routes: []
});
404页面
写一个NotFound.vue页面
<template>
<div>
<h1>404,你的页面走丢了h1>
div>
template>
配置路由
import NotFound from '../views/NotFound'
routes:[
{
path: '*', //匹配不到的走这个路径
component: NotFound
}
]
路由钩子
export default {
name: "Profile",
beforeRouteEnter:(to,from,next)=>{
console.log("进入路由之前");
next();
},
beforeRouteLeave:(to,from,next)=>{
console.log("进入路由之后");
next();
}
}
参数说明:
to:路由将要跳转的路径信息from:路径跳转前的路径信息next:路由的控制参数 next() 跳入下一个页面next(‘/path’) 改变路由的跳转方向,使其跳到另一个路由next(false) 返回原来的页面next((vm)=>{}) 仅在beforeRouteEnter中可用,vm是组件实例在钩子函数中使用异步请求
1. 安装Axios:cnpm install axios -s
2. main.js引用Axios
import axios from 'axios';
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
3. 准备目录。只有我们的static目录下的文件是可以被访问到的,所以我们把静态文件(data.json)放入该目录下。
4. 在beforeRouteEnter中进行异步请求
export default {
name: "Profile",
beforeRouteEnter:(to,from,next)=>{
console.log("进入路由之前");
next(vm => {
vm.getData(); //进入路由之前执行getData
});
},
beforeRouteLeave:(to,from,next)=>{
console.log("进入路由之后");
next();
},methods: {
getData: function () {
this.axios({
method: 'get',
url: 'http://localhost:8080/static/mock/data.json'
}).then(function (response) {
console.log(response);
})
}
}
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)