- build.js ==> 生产环境构建脚本
- check-versions.js ==> 检查npm,node.js版本
- utils.js ==> 构建相关工具方法
- vue-loader.conf.js ==> 配置了css加载器以及编译css之后自动添加前缀
- webpack.base.conf.js ==> webpack基本配置
- webpack.dev.conf.js ==> webpack开发环境配置
- webpack.prod.conf.js ==> webpack生产环境配置
- dev.env.js ==> 开发环境变量
- index.js ==> 项目配置文件:端口号等在这里修改
- prod.env.js ==> 生产环境变量
基本上要做的事情都在这个目录里。里面包含了几个目录及文件:
- assets:资源目录,放置一些图片或者公共js、公共css。这里的资源会被webpack构建
- components:组件目录,我们写的组件就放在这个目录里面
- router:前端路由,我们需要配置的路由路径写在index.js里面
- App.vue:根组件
- main.js:入口js文件
- 先在components文件夹下增加.vue文件
- 为这个页面创建路由,可以在index.js文件夹下
- 编辑vue文件,在中写html;在中写js;在中写样式
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<div id="app">
<p v-if="flag">
今天天气很舒服!
p>
<p v-else-if="rich">
今天天气很燥热!晚上要去放松一下!
p>
<p v-else="rich">
晚上只能自嗨!
p>
<p v-show="rich">
有钱!
p>
div>
body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js">script>
<script>
new Vue({
el:'#app',
data:{
flag:false,
rich:false
},
methods:{
}
});
script>
html>
v-if是创建或者删除p,而v-show实际会将p标签的css样式的display属性设为none来达到隐藏的效果;所以在频繁变动的情况下,使用v-show的效率更高
普通for
<body>
<div id="app">
<ul>
<li v-for="a in args">{{a}}li>
ul>
div>
body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js">script>
<script>
new Vue({
el:'#app',
data:{
args:[1,2,3,4,5,6]
}
});
script>
带着索引的for
<body>
<div id="app">
<ul>
<li v-for=" (a,i) in args" :key='i'>{{i}}{{a}}li>
ul>
div>
body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js">script>
<script>
new Vue({
el:'#app',
data:{
args:[1,2,3,4,5,6]
}
});
script>
遍历一个对象中的信息: v、k、i
<body>
<div id="app">
<ul>
<li v-for="(v,k,i) in student">{{i+1}}--{{k}}--{{v}}li>
ul>
div>
body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js">script>
<script>
new Vue({
el:'#app',
data:{
student:{
username:'小鱼',
age:20,
girl:'如花'
}
}
});
script>
v、k、i 这几个字符可以自己定义,分别表示每次循环内容的值、键、序号。
- v: 循环中每条数据的值 小鱼、20、如花
- k: 循环中每天数据的键 username、age、girl
- i: 循环的序号,从0开始
遍历一个对象数组:嵌套for
<body>
<div id="app">
<ul>
<li v-for=" student in students">
<span v-for="(v,k,i) in student">{{i+1}}--{{k}}--{{v}}span>
li>
ul>
div>
body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js">script>
<script>
new Vue({
el:'#app',
data:{
students:[
{
name:'xiaoming',
age:20
},
{
name:'xiaowang',
age:21
}
]
}
});
script>
通过v-model将标签的value值与vue对象中的data属性值进行绑定
{{title}}
<html>
<head>
<meta charset="utf-8" />
<title>title>
head>
<body>
<div id="app">
<input type="text" v-model="title">
{{title}}
div>
body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
title:"hello vue"
}
})
script>
html>
通过这种方式,vue中的数据和输入框中的数据就能保持一致,互相变化
插值表达式是不能用在html的标签的属性内,如果一定要用vue的值作为html的标签的属性的内容,可以使用v-bind
<html>
<head>
<meta charset="utf-8" />
<title>title>
head>
<body>
<div id="app">
<a v-bind:href="link">a>
div>
body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
link:'http://www.baidu.com'
}
})
script>
html>
这样,a标签内的href属性就可以使用vue对象中的属性值。
注意: v-bind也可以简写,使用冒号“:”来代替
<a v-bind:href='link'>a> ==> <a :href='link'>
el用来指明vue挂载的元素,可以实String或者element
render方法的实质就是生成template模板
cli2中
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
cli3中
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
new Vue()就是一个构造函数,用来生成一个Vue实例
export default{}是用来将实例导出,可以在别的文件中,通过import被引用
关于事件,要把握好三个步骤:
- 设参
- 传参
- 接参
例如
- 设参:
- 传参:increase:function(s)
- 接参:this.sum+=s
<html>
<head>
<meta charset="utf-8" />
<title>title>
head>
<body>
<div id="app">
sum={{sum}}<br/>
{{sum>10?'总数大于10':'总数不大于10'}}<br/>
<button type="button" @click="increase(2)">增加button>
div>
body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
sum:0
},
methods:{
increase:function(s){
this.sum+=s
}
}
})
script>
html>
通过具体的事件名,绑定vue中定义的函数
<html>
<head>
<meta charset="utf-8" />
<title>title>
head>
<body>
<div id="app">
<input type="text" v-on:click="changeMajor" />
div>
body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
major:'java'
},
methods:{
sayHi:function(){
alert("HELLO VUE!");
},
changeMajor:function(){
console.log("change Title")
}
}
script>
html>
此时,该按钮,在点击时将会调用Vue对象中定义的changeMajor方法。
注意: v-on也可以简写,使用"@"替代。
<input type="text" @click="changeMajor" />
vue中将JavaScript中一些原生的Dom事件进行了封装,更加便于操作
.
stop
:等同于event.stopPropagation(),防止事件冒泡.
prevent
:等同于event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播).
capture
:与事件冒泡的方向相反,事件捕获由外到内.
self
:只会触发自己范围内的事件,不包含子元素.
once
:只会触发一次
可参考:
https://www.cnblogs.com/xuqp/p/9406971.htm
说明
- methods:定义方法,调用方法使用 currentTime1(),需要带括号
- computed:定义计算属性,调用属性使用 currentTime2,不需要带括号;this.message 是为了能够让 currentTime2 观察到数据变化而变化
注意:methods 和 computed 里不能重名
调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这一点;计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销
<html>
<head>
<meta charset="UTF-8">
<title>布局篇 计算属性title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js">script>
head>
<body>
<div id="vue">
<p>调用当前时间的方法:{{currentTime1()}}p>
<p>当前时间的计算属性:{{currentTime2}}p>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#vue',
data: {
message: 'Hello Vue'
},
methods: {
currentTime1: function () {
return Date.now();
}
},
computed: {
currentTime2: function () {
this.message;
return Date.now();
}
}
});
script>
body>
html>
要想实现组件化,需要在页面中注册组件:关于注册的方式有两种,分别是全局注册和本地注册。
组件包含了三个部分:template(html视图层内容)、script(Model层)、style(CSS样式)
使用Vue.compent()实现组件的全局注册,全局注册后可以重复使用
vue的全局注册,也就意味着在页面的任意一个被vue绑定过的div中,都可以使用全局注册了的vue组件。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue组件的全局注册title>
head>
<body>
<div id="app">
<model1>model1>
<model1>model1>
<model1>model1>
div>
<hr/>
<div id="app1">
<model1>model1>
<model1>model1>
<model1>model1>
div>
body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js">script>
<script>
//通过Vue.component实现组件的全局注册,全局注册后的组件可以被重复使用。
Vue.component("model1",{
template:"{{title}}
",
data:function(){
return {
title:"hello vue"
}
},
methods:{
btnfn:function(){
alert("hello !!!");
}
}
});
new Vue({
el:'#app'
})
new Vue({
el:'#app1'
})
script>
html>
**使用new Vue();的方式进行本地注册
但是,如果是对vue组件进行本地注册,那么在其他被vue绑定的div中,不能使用该组件
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue组件的本地(局部)注册title>
head>
<body>
<div id="app">
<model11>model11>
div>
<hr/>
<div id="app1">
<model11>model11>
div>
body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js">script>
<script>
new Vue({
el:'#app',
components:{
"model11":{
template:"{{title}}
",
data:function(){
return {
title:"hello vue"
}
},
methods:{
btnfn:function(){
alert("hello !!!");
}
}
}
}
})
new Vue({
el:'#app1'
})
script>
Vue中的组件也是有生命周期的。一个Vue组件会经历:初始化、创建、绑定、更新、销毁等阶段,不同的阶段,都会有相应的生命周期钩子函数被调用
<html>
<head>
<meta charset="UTF-8">
<title>生命周期title>
head>
<body>
<div id="app1">
{{title}}
<button type="button" @click="changeTitle">change titlebutton>
<button type="button" @click="destroy">destroybutton>
div>
body>
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js">script>
<script>
new Vue({
el:"#app1",
data:{
title:"this is title"
},
methods:{
changeTitle:function(){
this.title= "new title";
},
destroy:function(){
this.$destroy();
}
},
beforeCreate(){
console.log("beforeCreate")
},
created(){
console.log("created")
},
beforeMount(){
console.log("beforeMount")
},
mounted(){
console.log("mounted")
},
beforeUpdate(){
console.log("beforeUpdate")
},
updated(){
console.log("updated")
},
beforeDestroy(){
console.log("beforeDestory")
},
destroyed(){
console.log("destory")
}
})
script>
html>
通过子组件的props部分,来指明可以接收的参数,父组件通过在标签中写明参数的键值对来传递参数。
props是表示一个组件的参数部分,那么props的写法有两种:
1)props:[参数列表]
比如: props:[‘MyProp1’,‘MyProp2’,…]
2)props:{参数名1:{type:String,required:true,default:‘XX’},参数名2:{…}}
创建子组件
<template>
<div>
商品列表...
{{MyTitle}}
<button type="button" @click="btnfn('hello java')">点我button>
div>
template>
<script>
export default {
name: "Content.vue",
props:{
'MyTitle':{
type:String,
required:true,
default:'XX'
},
'btnfn':{
type:Function
}
}
}
script>
<style scoped>
style>
注册子组件:在main.js中注册子组件
import Vue from 'vue'
import App from './App.vue'
//引入Content
import Content from './components/Content'
//全局注册组件
Vue.component('MyContent',Content);
new Vue({
el: '#app',
render: h => h(App)
})
创建父组件
<template>
<div id="app">
<MyContent :MyTitle="msg" :btnfn="FCfn" >MyContent>
div>
template>
<script>
import MHeader from './components/Header'
export default {
name: 'app',
data(){
return {
msg:'hello vue!!'
}
},
components:{
"MHeader":MHeader
},
methods:{
FCfn:function(m){//hello java
this.msg = m;
}
}
}
script>
<style>
style>
通过使用路由,可以实现页面的跳转
使用路由的方式有两种:
- 通过
- 通过程序式路由
安装路由模块
npm install vue-router -s
在main.js中引入路由并使用
import Vue from 'vue'
import App from './App'
import router from './router' //引入路由模块
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router, //使用路由模块
components: { App },
template: ' '
})
<template>
<div id="app">
<ul class="nav nav-tabs">
<li role="presentation" class="active"><router-link to="/Home">首页router-link>li>
<li role="presentation"><router-link to="/Product">商品列表router-link>li>
ul>
<router-view/>
div>
template>
<script>
export default {
name: 'App'
}
script>
<template>
<div>首页div>
template>
<script>
export default {
name: "Home"
}
script>
<style scoped>
style>
<template>
<div>商品列表 商品的id:{{id}}div>
template>
<script>
export default {
name: "Product",
data(){
return{
id:this.$route.params.id //接参
}
}
}
script>
<style scoped>
style>
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Home from "../components/Home";
import Product from "../components/Product";
Vue.use(Router)
export default new Router({
routes: [
{
path:'/Home',
component: Home
},
{
path:'/Product/:id', //设参
component:Product
}
]
})
在路由表中设参
export default new Router({
routes: [
...
{
path:'/Product/:id', //设参
component:Product
}
]
})
在App.vue中传参
<template>
<div id="app">
<ul class="nav nav-tabs">
...
<li role="presentation"><router-link to="/Product/1">商品列表router-link>li>
...
ul>
<router-view/>
div>
template>
在Product.vue中接参
<template>
<div>商品列表 商品的id:{{id}}div>
template>
<script>
export default {
name: "Product",
data(){
return{
id:this.$route.params.id //接参
}
}
}
script>
<style scoped>
style>
使用进行路由跳转是有局限性的,可以通过**this.$router.push(’/Product/1’)**的js方式实现路由跳转,更加灵活。
<template>
<div id="app">
<ul class="nav nav-tabs">
<li role="presentation" class="active"><router-link to="/Home">首页router-link>li>
<li role="presentation"><router-link to="/Product">商品列表router-link>li>
<button type="button" @click="btnfn">点我button>
ul>
<router-view/>
div>
template>
<script>
export default {
name: 'App',
methods:{
btnfn(){
//代替router-link实现路由跳转
this.$router.push("/Product/1");
}
}
}
script>
安装vue axios
npm install --save axios vue-axios
在main.js中引入
import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
在function中这样写
his.axios({ method:'get', url:'http://localhost:8090/regist?mail='+this.mail+'&password='+this.password, }).then(function (response) { console.log(response.data) });
<template>
<div id="app">
<div style="width:50%" class="container">
<div>
<h3>Registh3>
<h5>Emailh5>
<input type="text" class="form-control" v-model="mail" /><br />
{{mail}}
<h5>Passwordh5>
<input type="password" class="form-control" v-model="password" /><br />
{{password}}
<h5>Genderh5>
<input type="radio" name="gender" v-model="gender" value="female" />男
<input type="radio" name="gender" v-model="gender" value="male" />女<br />
<h5>Hobbyh5>
<input type="checkbox" name="hobby" v-model="hobby" value="music">音乐
<input type="checkbox" name="hobby" v-model="hobby" value="movie">电影
<input type="checkbox" name="hobby" v-model="hobby" value="sport">运动
<br/>
<button type="button" class="btn btn-success" @click="registfn">注册button>
div>
div>
div>
template>
<script>
import MHeader from './components/Header'
export default {
name: 'app',
data(){
return {
mail:'',
password:'',
gender:'',
hobby:''
}
},
methods:{
registfn:function(){
this.axios({
method:'get',
url:'http://localhost:8090/regist?mail='+this.mail+'&password='+this.password,
}).then(function (response) {
console.log(response.data)
});
}
}
}
script>
跨域:域名、端口号、协议(http/https)任何一个不相同都属于跨域
在spring-mvc.xml中加入这一段。其中,allowed-origins指的是允许的访问源的域名,"*"表示任何人都可以访问,也可以指明具体的域名
<mvc:cors>
<mvc:mapping path="/" allowed-origins="*" allowed-methods="POST, GET, OPTIONS, DELETE, PUT,PATCH" allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With" allow-credentials="true" />
mvc:cors>
原因:默认情况下发送axios时请求头中的内容类型为: (后端没有使用@RequestBody)
Content-Type:application/json;charset=UTF-8
而实际服务端需要的是:
Content-Type:application/x-www-form-urlencoded
因此,使用axios的qs内置库中的方法进行内容类型的转换
import Qs from 'qs'
this.axios({
method:'post',
url:'http://localhost:8081/regist',
transformRequest: [function (data) {
return Qs.stringify(data)
}],
data:{
email:this.email
}
})
.then(function (response) {
alert(response.data.message)
});