Vue 学习
一、Vue 简介
Vue 是基于ES6规范并结合了AngulaJS的模块化开发和React的虚拟DOM,虚拟DOM就是把DOM操作放到内存中执行
什么是MVVM
他区别与MVC模式,MVC模式大致流程是view发送请求,通过controller,操作Model数据之后,结果通过controller返回View,view处理结果,展示给用户
而MVVM模式则是,view其实只做显示用,实际请求由ViewModel发出,Model处理完数据之后,ViewModel接收到数据,因为ViewModel和View是双向绑定的
所以数据会直接展示在View层。
二、Vue入门
1. 简单环境搭建
- 以idea,为例,通过file–settings-plugins,安装vue.js
- 将idea环境调成ES6,以为vue是基于es6规范写的,防止写代码时报错
2. 条件和循环
注意需要引入<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id = "app">
{{word}}
<li v-for="item in items">
{{item.message}}
</li>
</div>
<div id = "app2">
<h1 v-if="word==='A'">A</h1>
<h1 v-else-if="word==='B'">B</h1>
<h1 v-else-if="word==='D'">D</h1>
<h1 v-else>C</h1>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app2',
data :{
word : 'A'
}
});
var vm = new Vue({
el: '#app',
data :{
word : 'B',
items: [
{message: 'Hello Vue!', message:'2'},
{message: 'Hello Vue2!'}
]
}
});
</script>
</html>
3.绑定事件v-on
v-on 用于绑定事件,可以使用@符号代替
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">两级反转</button>
</div>
<div id="app2">
<p>{{ message }}</p>
<button v-on:click="reverseMessage2('嗨森')">两级反转</button>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
message: '不嗨森'
},
methods:{
reverseMessage:function () {
alert(this.message.split(''));
alert(this.message.split('').reverse());
//split将字符串变成字符数组
//reverse将字符数组反转,变成新数组
//join,将字符数组变成字符串
this.message = this.message.split('').reverse().join('')
}
}
});
var vm = new Vue({
el: '#app2',
data: {
message: '不嗨森'
},
methods:{
reverseMessage2:function (message) {
this.message = message;
}
}
});
</script>
</html>
4.数据双向绑定v-model
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app-6">
<p>{{ message }}</p>
<input v-model="message">
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
var app6 = new Vue({
el: '#app-6',
data: {
message: 'Hello Vue!'
}
})
</script>
</html>
5.给组件绑定参数v-bind
将参数传给绑定的组件中,组件中使用props接收,可以使用:符号代替
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<myli v-for="item in items" v-bind:temp="item"></myli>
<!-- <myli v-bind:test="message"></myli>-->
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
Vue.component("myli", {
props:['temp', 'test'],
template:'<li>{{temp}}</li>'
});
var vm = new Vue({
el: '#app',
data: {
items: ['Java','Vue','Linux']
}
})
</script>
</html>
6.组合组件slot插槽
组件内部事件绑定事件需要使用 this.$emit(‘事件名’, 参数)调用
以下为双击删除,指定的<li>
,由于<li>
是组件化的,所以删除它, 需要删除它绑定的数据,即items中的值,但是组件并不能直接访问到Vue中的数据
所以需要通过view层绑定一个自定义事件customremove,然后组件中通过this.$emit(‘customremove’, 参数)去调用,从而实现删除标签的功能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="(item,index) in items"
:item="item" :index="index" @customremove="removeItem(index)"></todo-items>
</todo>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
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','index'],
template: '<li>{{item}}---<button @dblclick="remove(index)">删除</button></li>',
methods:{
remove: function (index) {
this.$emit('customremove', index)
}
}
});
var vm = new Vue({
el: '#app',
data: {
title:'课程',
items: ['Java','Vue','Linux']
},
a:{
},
methods:{
removeItem:function (index) {
//删除当前下标元素,splice操作数组的万能方法
this.items.splice(index, 1);
}
}
})
</script>
</html>
7.计算机属性
计算机属性是Vue的特色,可以理解成缓存,可以理解成,计算过1+1等于2后,下一次在遇到1+1就直接使用缓存中的数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<p>currentTime1 {{currentTime1()}}</p>
<p>currentTime2 {{currentTime2}}</p>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
message:'123'
},
methods:{
currentTime1:function () {
return Date.now()
}
},
computed:{
//currentTime2的结果被缓存在内存中,如果其中的值被改变,值才会别刷新,
// 如message改变,currentTime2返回的值就会别改变
currentTime2:function () {
this.message;
return Date.now()
}
}
})
</script>
</html>
8.axios简单使用
注意需要引入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<!-- 解决屏闪问题 -->
<style>
[v-cloak] {
display: none !important;
}
</style>
<body>
<div id="app" v-cloak>
<ul v-for="(site,index) in info.sites">
<li>
{{index}}----{{site.name}}
</li>
</ul>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var vm = new Vue({
el: '#app',
data(){
return {
info:{
sites:[
{name:null,url:null}
]
}
}
},
// data:{
// info:[]
// },
mounted(){
axios.get('data.json').then(response=>(this.info=response.data))
}
})
</script>
</html>
data.json
{
"sites": [
{ "name":"百度" , "url":"www.baidu.com" },
{ "name":"google" , "url":"www.google.com" },
{ "name":"微博" , "url":"www.weibo.com" }
]
}
三、Vue项目
1.环境搭建
1.1 node.js 安装
https://nodejs.org/en/download/
直接在官网上下载安装包,无脑安装下一步就行,环境变量安装时会自动配置好
在cmd中输入,node -v可以确认是否安装成功
1.2 安装cnpm
安装node时,会自动安装一个npm,npm就相当于下载包的一个工具,类似linux的yum
但是npm有时安装会很卡,所以可以安装淘宝的cnpm,两个可以切换使用,但是尽量使用npm
#-g表示,全局安装
npm install cnpm -g
#或者想要加速的话可以每次加上仓储地址,但是每次都要,很麻烦,推荐使用第一种
npm install --registry=https://registry.npm.taobao.org
1.3 安装vue-cli
cnpm install vue-cli -g
#测试是否成功
#查看可以基于哪些模板创建vue程序,通常选择webpack
vue list
1.4 创建一个vue-cli 应用程序
- 在一个新的文件夹中使用命令行执行
#这里的myvue是项目名,可以改,第一次执行,可能会很慢,如果报错,按照提示执行相应的命令
vue init webpack myvue
- 执行时,需要填写些信息
#项目名
? Project name myvue
#项目描述
? Project description A Vue.js project
项目作者
? Author wangzhen
构建时编译方式,选择第一个运行时编译,Runtime + Compiler: recommended for most users
? Vue build (Use arrow keys)
> Runtime + Compiler: recommended for most users
Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specific HTML) are ONLY allowed in .vue files - re
nder functions are required elsewhere
是否安装vue-router,选择no,后面熟悉后都可以选择yes
? Install vue-router? No
是否使用ESLint,选择no
? Use ESLint to lint your code? no
? Setup e2e tests with Nightwatch? no
是否安装测试,选择no
? Set up unit tests No
是否执行npm install,选择No, I will handle that myself
? Should we run `npm install` for you after the project has been created? (recommended)
Yes, use NPM
Yes, use Yarn
> No, I will handle that myself
- 启动,执行一下命令
#切换目录
cd test-vue
#安装依赖环境
npm install
#运行
npm run dev
-
运行成功之后,可以通过http://localhost:8080 访问项目
-
用idea直接打开这个项目,然后可以通过修改config/index.js来修改端口,然后再次在idea执行,npm run dev,但是有时候执行不了,提示npm不是内部或外部命令,则是权限不够,可以通过快捷方式的属性,每次以管理员身份启动即可
-
另外,启动出现一些错误,可能是package的版本不对,可以打开根目录下的package.json去调整
2.webpack介绍
webpack学习使用:https://www.bilibili.com/video/BV18E411a7mC?p=14
主要作用,现在很多浏览器都是基于ES5, 而Vue是基于ES6的,所以需要通过webpack将ES6打包成ES5规范的
2.1安装webpack
npm install webpack -g
npm install webpack-cli -g
#测试是否安装成功
webpack -v
webpack-cli -v
2.2 webpack结构
查看刚才idea项目里的build/webpack.*.conf.js,这个js里可以配置一些打包时的参数
比如端口,程序入口,开发生产环境配置等
- entry:入口文件
- output:输出,执行webpack把处理完的文件放到指定目录
- module:模块,处理各种类型的文件
- plugins:插件,如:热更新、代码重用等
- reslove:设置路径指向
- watch:监听,用于设置文件改动后直接打包
2.3 使用webpack
-
创建一个项目webpack-test项目
-
创建一个modules文件夹
-
添加hello.js
//暴露一个方法 exports.sayHi = function () { document.write("<h1>Hello, Vue!学习VUE真嗨森!</h1>"); }
-
创建一个main.js
//使用require接收hello var study = require("./hello"); //调用hello的暴露的方法 study.sayHi();
-
创建一个webpack.config.js,将模块打包
module.exports = { entry:"./modules/main.js", output:{ filename:"./js/bundle.js" } };
-
命令行执行 webpack,就会生成一个dist,里面有个js/bundle.js
-
新建一个index.html引用这个js/bundle.js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script src="dist/js/bundle.js"></script> </body> </html>
-
然后直接打开这个页面就会看到
2.4总结
上面那个项目,就很好的说明了webpack的作用,就是webpack.config.js通过entry指定js入口,然后,main.js接收所有的js,统一通过webpack将程序打包成一个ES5规范的js,然后直接引用。只不过,这些过程在vue项目已经被做好了,后面会提到
3.vue-router介绍
vue-router是Vue官方的路由管理器,
3.1 主要作用
3.2 安装
idea打开之前的myvue项目,执行安装命令
#安装vue-router, --save-dev表示保存到当前dev环境,失败了可以使用cnpm
npm install vue-router --save-dev
3.3路由使用
目录结构
-
创建一个组件Content.vue
<template> <h1>内容页</h1> </template> <script> export default { name: "Content" } </script> <style scoped> </style>
-
Main.vue
<template> <h1>首页</h1> </template> <script> export default { name: "Main" } </script> <style scoped> </style>
-
创建路由管理router.js
先从vue-router导入VueRouter,然后安装路由Vue.use(VueRouter),最后将新的配置好的路由通过export default new VueRouter({})导出
import Vue from 'vue' import VueRouter from 'vue-router' import Content from '../components/Content' import Main from '../components/Main' //安装路由 Vue.use(VueRouter); //配置导出路由 export default new VueRouter({ routes:[ { path:'/content', name:'content', component:Content }, { path:'/main', name:'main', component:Main } ] });
-
程序入口(前面讲到,可以在webpack配置文件中修改入口)main.js导入路由,分为两步
-
程序入口导入路由
-
Vue对象(这个vue对象时全局唯一)中配置路由
import Vue from 'vue' import AppTest from './App' //1.导入路由,自动扫描里面的配置文件 import router from './router' Vue.config.productionTip = false new Vue({ el: '#app', //2. 配置路由 router, a:{ }, components: { AppTest }, template: '<AppTest/>' })
-
-
在APP.vue中使用路由
- router-link,可以认为是
<a>
标签,通过to,可以跳到指定的路由 - router-view,用于展示页面
<router-link to="/main">首页</router-link> <router-link to="/content">内容页</router-link> <router-view></router-view>
<template> <div id="app"> <h1>Vue学习</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>
- router-link,可以认为是
4. Vue项目搭建
4.1初始化项目
# 通过vue-cli提供的webpack模板初始化项目,一路选择no
vue init webpack hello-vue
# 进入工程
cd hello-vue
# 安装路由
npm install vue-router --save-dev
# 安装element-ui
npm i element-ui -S
# 安装SASS 加载器,注意SASS可能自动安装的版本太高了,如果报错需自行到package.json中调整成7.3.1
npm install sass-loader node-sass --save-dev
# 启动测试
npm run dev
4.2 实现登录功能
实现流程和路由使用是一样的,创建登录组件,然后创建路由管理router.js,然后入口main.js引用路由,然后主程序app.vue使用
项目详情参考https://github.com/MilesWang-Zhen/hello-vue
5.其他知识点
5.1 路由嵌套
就是路由底下还可以写路由,通过children嵌套,下面就是在main下面嵌套两个页面/user/profile/,/user/list
export default new VueRouter({
mode:'history',
routes:[
{
path:'/main/:username',
component:Main,
props:true,
children:[
{
path:"/user/profile/:id",
name:"UserProfile",
component:UserProfile,
props:true
},
{
path:"/user/list",
component:UserList
}
]
},
{
path:'/login',
component:Login
},
{
path:'/goHome',
redirect:'/Login'
},
{
path:'*',
component:NotFound
}
]
});
5.2 参数传递
-
可以在router-link的to属性中添加参数,name为路由中配置UserProfile,params为参数
<router-link :to="{name:'UserProfile', params:{id:1}}">个人信息</router-link>
-
然后在路由配置中的path添加上id
path:"/user/profile/:id"
-
然后在Profile.vue中可以使用,有两种使用方式
-
第一种,注意{{$route.parms.id}}需要被被其他标签包裹,不能直接写在
<template>
中```html <template> <!-- 所有元素,一定不能在根节点下,否则会报错 --> <div> <h1>个人信息</h1> {{$route.parms.id}} </div> </template> <script> export default { name: "UserProfile" } </script> ```
-
第二种,需要在路由中配置props:true,然后再组件中使用props:[‘id’]接收,最后再使用
``` html <template> <div> <h1>个人信息</h1> {{id}} </div> </template> <script> export default { props:['id'], name: "UserProfile" } </script> ```
5.3页面重定向
在路由router.js中直接加上这段配置,然后通过
{
path:'/goHome',
redirect:'/login'
},
5.4 去除访问地址中的#号
可以修改路由的mode, mode默认是hash模式,hash模式会带个#,可以改成history
mode:'history',
5.5简单处理404
添加一个NotFound组件,然后在路由中监听所有path的配置,一般写在最后,如果前面的都没进,就会到404页面
{
path:'*',
component:NotFound
}
5.6钩子函数
以Profile组件为例
<template>
<div>
<h1>个人信息</h1>
{{id}}
</div>
</template>
<script>
export default {
props:['id'],
name: "UserProfile",
beforeRouteEnter:(to, from, next)=>{
console.log("进入路由");
next(vm => {
vm.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);
})
}
}
}
</script>
<style scoped>
</style>
beforeRouteEnter在进入路由之前执行,beforeRouteLeave在离开路由之前执行,一定需要写next(),不然就走不到下一个钩子了,有点类似于java过滤器
参数解释:
5.7在钩子函数中使用axios
-
安装axios, 当然使用axios的使用,也可以通过script的方式
cnpm install axios -s
-
main.js 中引用Axios
import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(VueAxios, axios)
-
创建测试数据
注意data.json需要放在static中才能直接访问到
{ "sites": [ { "name":"百度" , "url":"www.baidu.com" }, { "name":"google" , "url":"www.google.com" }, { "name":"微博" , "url":"www.weibo.com" } ] }
-
axios获取数据
在组件中添加methods属性, 然后在next()里直接拿到Vue对象vm(vm只是个变量名,可随意写),然后调用methods中的getData(),可以获取response
export default { props:['id'], name: "UserProfile", beforeRouteEnter:(to, from, next)=>{ console.log("进入路由"); next(vm => { vm.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); }) } } }
参考资料
B站学习视频:https://www.bilibili.com/video/BV18E411a7mC
学习笔记:https://blog.csdn.net/jzandth/category_10414568.html
Vue生命周期