以下是本人学习的观点,如果有错或者说得不全面,记得告诉我哟
Vue是什么
官网说Vue是一套用于构建用户界面的渐进式框架,起初我也不知道渐进式是什么,大概就是想要什么添加什么,在了解一些基础后,觉得vue就是把原本我们要写很多原生html,js,css代码直接封装了,目的就是尽量让对代码不熟悉的人都能够进行学习,和python一样,都是为了方便。同时Vue只在视图层,这意味这写完这个代码,可以直接把代码扔给后端人员,并且不会影响后端的开发。
为什么要使用Vue
就是方便,而且如果想改前端,后端不用修改,只是把传送的接口再连上即可。而且代码比较人性化,容易上手,容易通过读代码就能理解是这个功能是什么,不过还是要进行学习。而且是响应式的,响应式就是说一写完就立刻变化,不用重新执行,提高了开发效率。
第一个Vue程序
idea配置vue环境
1.先下载插件
2.然后新建一个vue新建项,这里
https://blog.csdn.net/weixin_43906969/article/details/112305930
新建一个vue文件并插入vue的cdn
这个注意看div的id是app,而下面script是app的配置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
{{message}}
</div>
<!-- 1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm=new Vue({
//Model:数据
el:"#app",
data:{
message:"hello,vue!"
}
});
</script>
</body>
</html>
常用的vue功能
判断条件v-if、v-else-if和v-else用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
<h1 v-if="type==='A'">A</h1>
<h1 v-else-if="type==='B'">B</h1>
<h1 v-else>C</h1>
</div>
<!-- 1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm=new Vue({
//Model:数据
el:"#app",
data:{
type: 'A'
}
});
</script>
</body>
</html>
循环v-for
-<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
<li v-for="item in items">
{{item.message}}
</li>
</div>
<!-- 1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm=new Vue({
//Model:数据
el:"#app",
data:{
items: [
{message: '一峰说java'},
{message: '一峰说前端'},
{message: '一峰运维'}
]
}
});
</script>
</body>
</html>
绑定事件v-on:click
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
<button v-on:click="sayHi">点击我</button>
</div>
<!-- 1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm=new Vue({
//Model:数据
el:"#app",
data:{
message: "一峰说java"
},
methods: {//方法必须定义在Vue的Method对象中
sayHi :function (){
alert(this.message);
}
}
});
</script>
</body>
</html>
双向绑定v-model
就是可以边写边显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
<p>
输入的文本:<textarea v-model="message"></textarea>{{message}}
</p>
<p>
性别:
<input type="radio" name="sex" value="男" v-model="fever1">男
<input type="radio" name="sex" value="女" v-model="fever1">女
<p>
选中了: {{ fever1 }}
</p>
</p>
<p>
下拉框:
<select name="" id="" v-model="fever2">
<option value="" disabled>---请选择---</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>{{fever2}}</span>
</p>
</div>
<!-- 1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm=new Vue({
//Model:数据
el:"#app",
data:{
message: "",
fever1: "",
fever2: ""
}
});
</script>
</body>
</html>
组件化应用构建
可以理解自己定义组件,下面这个代码我觉得不够vue官网的那个好,因为下面这个少了v-bind:key用法,用力绑定id的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
<!--组件: 传递给组件中的值:props-->
<fever v-for="item in items" v-bind:todo="item"></fever>
</div>
<!-- 1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
//定义一个Vue组件名字叫fever
Vue.component("fever",{
props: ['todo'],//props是绑定一个属性,并且名字是item
template: '<li>{{todo}}</li>'//
});
var vm=new Vue({
//Model:数据
el:"#app",
data:{
items: ["Java","Linux","前端"]
}
});
</script>
</body>
</html>
使用异步通信axios
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- v-clock:解决闪烁问题,就是打开网页的时候,可能会因为网络加载太慢问题先出现空白-->
<style>
[v-clock]{
display: none;
}
</style>
</head>
<body>
<div id="vue" v-clock>
<div>{{info.name}}</div>
<div>{{info.address.street}}</div>
<a v-bind:href="info.url">去我博客</a>
</div>
//记得导入这个axios异步cdn
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
var vm=new Vue({
el: "#vue",
//data: 属性:vm
data(){
return{
//请求的的返回参数合适,必须和json字符串一样
info: {//简介
name: null,//姓名
url: null,//url地址
address: {//地址
street: null,//街道
city: null,//城市
country:null //国家
}
}
}
},
mounted(){ //钩子函数 链式编程 ES6新特性
axios.get('../data.json').then(response=>(this.info=response.data));//异步通信方式,data.json在下面
}
});
</script>
</body>
</html>
data.json:
{
"name": "fever说java",
"url": "https://blog.csdn.net/weixin_43906969?spm=1001.2101.3001.5343",
"page": 1,
"isNonProfit": true,
"address": {
"street": "香香街",
"city": "广东广州",
"country": "中国"
},
"links": [
{
"name": "csdn",
"url": "https://blog.csdn.net/weixin_43906969?spm=1001.2101.3001.5343"
},
{
"name": "fever说java",
"url": "https://blog.csdn.net/weixin_43906969?spm=1001.2101.3001.5343"
},
{
"name": "百度",
"url": "https://www.baidu.com"
}
]
}
计算属性
计算属性就是用来解决因为经常放太多模板导致很难维护的问题。就是在一个叫computed的属性里面使用变量函数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
<p>currentTime1:{{currentTime1()}}</p>
<p>currentTime2:{{currentTime2}}</p>
</div>
<!-- 1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm=new Vue({
//Model:数据
el:"#app",
data:{
message:"hello,fever!"
},
//方法属性
methods: {
currentTime1: function (){
return Date.now();//返回一个时间戳
}
},
computed: {//计算属性:methods,computed 方法不能重名,重名之后只会调用methods中的方法
currentTime2: function (){
return Date.now();//返回一个时间戳
}
}
});
</script>
</body>
</html>
插槽slot
先看div的部分,然后通过div里面的东西我们可以看到它和下面组件component有关(设置插槽标签),同时再下一个component也和插槽才是绑定数据。
可能这个数据传送看起来很懵,就是new Vue那面有数据了,然后传到div上面,接着div有插槽,其实插槽就是去到哪插到哪,方便位置而已,然后第二个component绑定了插槽数据并且有一个删除remove方法,点击的时候会执行new Vue里面的methods属性里面的方法。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="(item,index) in todoItems"
:item="item" v-bind:index="index" v-on:remove="removeItems(index)"//v-bind简写是:
></todo-items>
</todo>
</div>
<!-- 1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.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','index'],
//只能绑定当前组件的方法
template: '<li>{{index}}---{{item}}<button @click="remove">删除</button></li> ',//@是v-on简写
methods: {
remove: function (index){
//this.$emit 自定义表
this.$emit('remove',index);
}
}
});
var vm=new Vue({
//Model:数据
el:"#app",
data:{
title: "王同学列表",
todoItems:['一峰说Java','一峰说前端','一峰说Linux']
},
methods: {
removeItems:function (index){
console.log("删除了"+this.todoItems[index]+"OK");
this.todoItems.splice(index,1);//一次删除一个元素
}
}
});
</script>
</body>
</html>
第一个vue-cli程序
vue-cli就是快速生成一个vue的项目模板
安装node.js
下载直接安装就可,不要放在c盘,它会自动配置环境变量。下载链接:http://nodejs.cn/download/
node -v 查看node.js版本
npm -v 查看npm软件包管理工具版本
安装node.js淘宝镜像加速器(cnpm)
npm install cnpm -g //-g是全局安装的意思
安装vue-cli
cnpm install vue-cli -g
创建一个基于webpack模板的vue应用程序
vue init webpack myvue
一路选no就可以了,东西需要再加
初始化并运行vue项目
如果想在idea上执行命令,记得把idea设置为管理员权限
cd myvue //进入vue项目
npm install
npm run dev
或者
cnpm install
cnpm run dev
学习Webpack
webpack就是一个js的静态模块打包器。
创建一个目录modules
1.导入一个方法
hello.js:
//暴露一个方法
exports.sayHi =function (){
document.write("<h1>一峰说ES6</h1>");
};
2。引用一个方法
main.js:
var hello = require('./hello');
hello.sayHi();
3.配置
webpack.config.js:
module.exports = {
entry: './modules/main.js',
output: {
filename: "./js/bundle.js"
}
};
4.生成配置文件
在idea当前项目所在目录下执行命令
webpack.config.js
5.插入显示
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--前段的模块化开发-->
<script src="dist/js/bundle.js"></script>
</body>
</html>
路由+elementUI+路由嵌套+参数传递+重定向+404+路由钩子
vue-router路由
1.首先安装
cnpm install vue-router --save-dev
2.在App.vue添加布局
<template>
<div id="app">
<h1>Vue-Router</h1>
<router-link to="/main">首页</router-link>
<router-link to="/content">内容页</router-link>
<router-link to="/xiaobu">小布</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>
3…在main.js导入router包
import Vue from 'vue'
import App from './App'
import router from './router' //自动扫描里面的路由配置
Vue.config.productionTip = false;
new Vue({
el: '#app',
//配置路由
router,
components: { App },
template: '<App/>'
})
4.配置router目录下index.js,这个一般是我们自己新建的
import Vue from 'vue'
import App from './App'
import router from './router' //自动扫描里面的路由配置
Vue.config.productionTip = false;//阻止启动生产消息,就是不会给我们报太多错
new Vue({
el: '#app',
//配置路由
router,
components: { App },
template: '<App/>'
})
5.router下的index.js配置
import Vue from 'vue'
import VueRouter from "vue-router";
import Content from "../components/Content";
import Main from "../components/Main";
import Xiaobu from "../components/Xiaobu";
//安装路由
Vue.use(VueRouter);
//配置导出路由
export default new VueRouter({
routes: [
{
//路由路径 @RequestMapping
path: '/content',
name: 'content',
//跳转的组件
component: Content
},
{
//路由路径
path: '/main',
name: 'main',
//跳转的组件
component: Main
},
{
//路由路径
path: '/xiaobu',
name: 'xiaobu',
//跳转的组件
component: Xiaobu
}
]
});
6.components文件夹,添加vue文件
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>
Xiaobu.vue:
<template>
<h1>小布</h1>
</template>
<script>
export default {
name: "Xiaobu"
}
</script>
<style scoped>
</style>
vue+elementUI
1.在main.js下导添加
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI)
new Vue({
el: '#app',
render: h => h(App)//ElementUI
})
2.添加页面样式即可,例如
路由嵌套
直接展示
参数传递
参数传递有页面直接操作和后端获取数据,后端一般会用axios,前段用url
页面直接操作:
这里固定是1,一般是可变的id
然后在router下的index.js对应的路径添加多一个name属性:
接着在对应vue文件绑定好参数
后端获取数据
简单说说就是在对应页面的script标签下写几行代码,这里是输出到控制台
一般结合vue-axios是要安装命令:
建议去axios的官网看看安装教程,很短的
npm install --save axios vue-axios
重定向
404
路由钩子
路由中的钩子函数,就是在路由前后有个函数,有时作用是过滤
完整的例子
目录:
App.vue:
<template>
<div id="app">
<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>
main.js
import Vue from 'vue'
import App from './App'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import router from './router'
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
Vue.use(router)
Vue.use(ElementUI)
new Vue({
el: '#app',
router,
render: h => h(App)//ElementUI
})
Login.vue
<template>
<div>
<el-card class="box-card">
<el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box">
<h3 class="login-title">欢迎登录</h3>
<el-form-item label="账号" prop="username">
<el-input type="text" placeholder="请输入账号" v-model="form.username"/>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" placeholder="请输入密码" v-model="form.password"/>
</el-form-item>
<el-form-item>
<el-button type="primary" v-on:click="onSubmit('loginForm')">登录</el-button>
</el-form-item>
</el-form>
</el-card>
<el-dialog
title="温馨提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<span>请输入账号和密码</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name:"Login",
data(){
return{
form:{
username: '',
password: ''
},
//表单验证,需要再el-form-item 元素中增加prop属性
rules:{
username:[
{required:true,message:'账号不能为空',trigger:'blur'} //trigger:'blur'失去焦点
],
password:[
{required: true,message: '密码不能为空',trigger:'blur'}
]
},
//对话框显示和隐藏
dialogVisible:false
}
},
methods:{
handleClose: function () {
console.log("Handle Close,空函数");
},
onSubmit(formName) {
//为表单绑定验证功能
this.$refs[formName].validate((valid) =>{
if (valid){
//使用 vue-router路由到指定页面,该方式称之为编程式导航
this.$router.push("/main");
} else {
this.dialogVisible = true;
return false;
}
});
}
}
}
</script>
<style lang="scss" scoped>
.login-box{
border: 1px solid #DCDFE6;
width: 350px;
margin:180px auto;
padding:35px 35px 15px 35px;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
box-shadow:0 0 25px #909399;
}
.box-card {width: 480px;margin: auto;}
.login-title{
text-align:center;
margin:0 auto 40px auto;
color:#303133;
}
</style>
Main.vue
<template>
<div>
<el-container>
<el-aside width="200px">
<el-menu :default-openeds="['1']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-caret-right"></i>用户管理</template>
<el-menu-item-group>
<el-menu-item index="1-1">
<router-link :to="{name: 'UserProfile',params: {id :1}}">个人信息</router-link>
</el-menu-item>
<el-menu-item index="1-2">
<router-link to="/user/list">用户列表</router-link>
</el-menu-item>
<el-menu-item index="1-3">
<router-link to="/goHome">回到首页</router-link>
</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-caret-right"></i>内容管理</template>
<e1-menu-item-group>
<el-menu-item index="2-1">分类管理</el-menu-item>
<el-menu-item index="2-2">内容列表</el-menu-item>
</e1-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header style="text-align: right; font-size: 12px">
<el-dropdown>
<i class="el-icon-setting" style="margin-right:15px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: "Main"
}
</script>
<style scoped lang="scss">
.el-header {
background-color: #048bd1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
NoFound.vue
<template>
<h1>404,你的页面走丢了</h1>
</template>
<script>
export default {
name: "NoFound"
}
</script>
<style scoped>
</style>
List.vue
<template>
<h1>用户列表</h1>
</template>
<script>
export default {
name: "List"
}
</script>
<style scoped>
</style>
Profile.vue
<template>
<div>
<h1>个人信息</h1>
{{ id }}
</div>
</template>
<script>
export default {
props: ['id'],
name: "Profile",
//过滤器 chain
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)
})
}
}
}
</script>
<style scoped>
</style>
index.js
import Vue from 'vue'
import Router from 'vue-router'
import Main from '../views/Main'
import Login from '../views/Login'
import UserList from '../views/user/List'
import UserProfile from '../views/user/Profile'
import NotFound from '../views/NoFound'
Vue.use(Router);
export default new Router({
mode: 'history',//去掉#号
routes:[
{
path: '/main',
component: Main, //嵌套路由
children:
[
{path: '/user/profile/:id',name: 'UserProfile',component:UserProfile,props:true},
{path: '/user/list',component: UserList},
]
},{
path: '/login',
component: Login
},{
path: '/goHome',
redirect: '/main'
},{
path: '*',
component: NotFound
}
]
});
mock是虚拟伪造的意思,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/"
}
]
}