Vue项目
1. npm/cnpm install vue-cli
1. 全局安装Vue脚手架工具,用于构建Vue项目,输入"vue"命令可检查是否成功
2. vue init webpack vue_demo ==> 构建一个Vue项目
1. webpack:模板名称; vue_demo:项目名称,不能包含大写字母;
3. cd vue_demo --> npm/cnpm install --> 初始化:下载模板等
4. npm/cnpm run dev --> 打包运行:http://localhost:8080/
1. "dev"在项目的package.json中的"scripts"下,表示开发环境运行;
Vue结构
1. build:webpack相关的配置文件
1. dev表示开发环境,prod表示生产环境;
2. config:webpack相关的配置文件
1. index.js:指定后台服务的host、port、静态资源文件夹
3. static:存放全局的资源,如CSS、图片等;
1. .gitkeep:为git服务,当static文件夹为空时,不忽略此文件夹;
4. src/main.js:入口文件; src/App.vue:根组件; src/components:子组件目录;
5. index.html:Vue最终的应用都是单页面的,组件最终打包到index.html中;
Vue项目打包与发布
1. 静态Web服务器发布
1. npm/cnpm run build --> 打包项目,默认生成disk目录,也就是可发布的应用
2. npm/cnpm install -g serve --> 全局安装一个静态服务器工具包
3. serve dist --> 运行可发布的应用
2. 动态Web服务器发布
1. 修改配置:webpack.prod.conf.js
output: {
publicPath: '/xxx/' --> 打包文件夹的名称,也即是项目名
}
2. npm/cnpm run build --> 重新打包项目
3. 修改disk文件夹为项目名称xxx,将该目录拷贝到运行tomcat的webapps目录下。
Vue语法二
1. main.js:入口文件,用于初始化Vue实例,引入根组件、路由、公共资源(如base.css)
1. 引入Vue和根组件:import Vue from 'vue',import App from './App.vue'
2. 引入base.css:import '../static/css/base.css'
也可以在index.html中引入:
<link rel="stylesheet" href="./static/css/base.css">
3. 初始化基本的Vue实例:
new Vue({
el: '#app', --> app即是index.html中<div>的id属性值;
components: { App }, --> 映射Vue组件,完整映射:{ 'App': App }
template: '<App />', --> 在模板中使用映射后组件
})
2. App.vue:根组件,用于引入其他子组件、定义公共的数组、协调子组件间的通信...
1. 组件的结构:<template><template> <script></script> <style></style>
2. <template>中用于HTML的布局,必须有一个唯一的根节点;
3. <style>中定义当前组件使用的CSS样式;
4. <script>负责逻辑:
<script>
import TodoHeader from './components/TodoHeader.vue' -->引入组件
export default { --> 默认暴露的方式
components: {
TodoHeader -->映射,可在<template>中直接使用<TodoHeader />
} --> 的方式引入组件TodoHeader.vue
} ----> 因为是两个单词,也支持使用<todo-header />
</script>
3. 在组件中,暴露的data属性,不能直接使用对象,必须是一个函数,返回一个对象;
data() {
return {
persons: [{name:'Mack', age:20},{name:'Any', age:17}]
}
},
methods: {
add(item){ -->操作数据的方法,通常和被操作的数据定义在同一个组件中
this.persons.unshift(item);
}
}
4. 向子组件传递的属性/方法:
1. 传递属性persons:<TodoHeader :persons="persons" />
2. 传递方法add():<TodoHeader :add="add" />
3. TodoHeader.vue中接收属性/方法:
export default {
props: { --> 用于声明接收的属性/方法,它们也会作为当前组件的属性/方法
persons: { -------> 通常写为:persons: Array
type: Array, --> 属性值的类型
required: true
},
add: { -------> 通常写为:add: Function
type: Function,
required: true
},
},
}
4. 子组件只能使用父组件的属性,而不能直接修改,只能通过调用父组件的方法,间接修改。
5. 鼠标进入、移除监听:onmouseenter、onmouseleave、onmouseover、onmouseout
<div id="box1">
<div id="box2"></div>
</div>
1. 给box1绑定事件onmouseenter和onmouseleave:
鼠标进入box1-->触发onmouseenter,再进入box2、离开box2-->没有任何响应,
离开box1-->触发onmouseleave
2. 给box1绑定事件onmouseover和onmouseout:
鼠标进入box1-->触发onmouseover,再进入box2-->触发onmouseout->onmouseover
离开box2-->触发onmouseout->onmouseover,离开box1-->触发onmouseout
3. Vue中鼠标事件的绑定:<div @mouseenter="enter" @mouseleave="leave">
6. 数据存储:window.localStorage.getItem('key')/setItem('key', value)
7. 自定义事件
1. 在App.vue中给子组件绑定自定义事件add:<TodoHeader @add="add" />
2. 在TodoHeader中触发该事件,回调App.vue中的add():
methods: {
addItem() {
item = {name:'Mack', age:20}
//触发自定义事件:参数1是事件名,参数2是参数
this.$emit('add', item);
}
}
3. 可用于替代父子组件,父组件向子组件传递函数,但不适用于父组件向孙组件传递;
4. 绑定自定义事件2:<TodoHeader ref="header" />
mounted() { --> 初始化组件实例时,给子组件绑定自定义事件add
this.$refs.header.$on('add', this.add);
} --> 子组件.$on('自定义事件名', 回调的方法名)
8. 事件的订阅与发布:非父子组件之间的通信,Vue2.0提供的bus.js、第三方PubSub.js库
1. bus是全局性的,一旦订阅,无论所在的组件是否初始化,都会接收到事件;
2. 如果bus的订阅被多次执行,会订阅多次,所以需要及时取消订阅。
9. slot:适用于父组件向子组件传递"标签数据",用于占位,便于复用同一个组件;
1. 在子组件TodoHeader.vue中定义好占位的插槽:
<div>
<slot name="ab"></slot>
<slot name="ef"></slot>
</div>
2. 在父组件App.vue中,向TodoHeader.vue的插槽传递对应的标签数据:
<TodoHeader>
<input type="text" slot="ab">
<div slot="ef">
</TodoHeader>
3. 这些标签结构是在父组件中编译完成之后,才传递给子组件的,所以标签的对应操作也必须定义
在父组件中,如事件绑定、属性、属性计算等等。
10. 封装工具模块storageUtil.js:
const KEY = 'persons'
export default { --> 默认模块的属性/方法
savePerson(person) {
window.localStorage.setItem(KEY, JSON.stringify(person))
},
readPerson(person) { --> 默认返回一个空数组
return JSON.parse(window.localStorage.getItem(KEY) || '[]')
},
}
1. 在Vue组件中引入工具模块:import storageUtil from './storageUtil'
2. storageUtil对象可以直接调用模块中暴露的方法;
3. 两种暴露方式:export、export default
export可以有多个,而export default只能有一个;
Vue网络请求
1. vue-resource:vue插件,非官方库,vue1.x广泛使用;
2. axios:通用的ajax请求库,官方推荐,vue2.x使用广泛,cnpm i axios --save
1. 引入:import axios from 'axios'
2. axios发送get请求:
axios.get('url').then(response => { --> 成功的响应
const result = response.data; --> 响应的数据
}).catch(error => { --> 失败的响应
alert(error);
});
Vue路由
1. 如果创建项目时没有安装路由,则手动安装:cnpm install vue-router --save
1. 在src目录下创建router目录,router目录下创建路由模块index.js
2. 在router/index.js中引入路由:import Router from 'vue-router'
import Vue from 'vue' --> 引入Vue
import About from '../views/About.vue' --> 引入src/views下的组件About
Vue.use(Router) --> 声明使用Vue
export default new Router({ ---> 暴露创建的VueRouter实例,配置路由
routes: [
{ path: '/about', component: About, name: 'about' },
{ path: '/', redirect: '/about' }, --> 自动跳转路由(重定向)
] ---> path:路由路径,即浏览器地址栏的URL;
}) ---> component:指向的Vue组件,称为路由组件;
---> name:路由名称,在编程式路由导航时使用;
3. 在main.js中的Vue实例中注册路由器: import router from './router'
new Vue({ ..., router, })
2. 使用路由组件标签:
1. <router-link>:生成路由链接,属性to的属性值必须与配置的path一致;
2. <router-view>:用于显示当前路由组件的界面;
<div>
<router-link to="/about">Go to About</router-link>
<router-link to="/home">Go to Home</router-link>
</div>
<router-view></router-view>
3. 命名视图
1. 一个路由可以对应多个路由组件,但只能同时显示,或只显示某些组件,不能动态更改
{
path: '/',
components: {
default: Foo,
nav: Nav,
main: Main
}
}
2. 通过<router-view>的name属性,同时显示三个组件:
<router-view></router-view> ---------> 默认组件:Foo
<router-view name="nav"></router-view> ---> Nav
<router-view name="main"></router-view> ---> Main
4. 嵌套路由:路由组件中还有路由链接,而且可以多层嵌套;
1. 配置About的子路由:import Msg from '../views/Msg.vue'
{ path: '/about', component: About,
children: [ {
path: '/about/msg', ---> 简写形式:path: 'msg'
component: Msg, name: 'msg' },
]
}
2. children下还可以配置子路由,通过子路由实现块级变化,而不用替换根路由。
5. 缓存路由组件
1. 切换路由组件A到路由组件B,那么A组件将被销毁,切换回来后又会重新创建;
2. 缓存路由组件(对象):<keep-alive> <router-view /> </keep-alive>
动态路由
动态路由:路由的路径携带参数
1. 把某种模式匹配的所有路由,映射到同一个组件,在path中使用":"标记;
1. 数据:message = [{id: 1, tip: 'abc'}, {id: 2, tip: 'efg'}]
2. 路由:{ path: '/user/:id', component: User } --> 接收参数id
<li v-for="(msg, index) in message" :key="msg.id">
router-link :to="`/user/${msg.id}`">{{msg.tip}}</router-link>
</li>
2. 路由组件对象中有当前路由对象:$route,包含了路由的路径、参数等信息;
1. path中":"标记的参数,传递的参数值会被设置到 this.$route.params
2. 在路由组件User中,获取传递的":id"参数值:this.$route.params.id
3. this.$route.path:获取完整的路由路径path
3. 多个路由匹配复用同一个路由组件,这就意味着该组件的勾子函数不会重复被调用;
1. 监听 $route 的变化,把初始化操作转移到watch的回调函数中;
watch: {
$route: (to, from) { --> to是当前 $route 的值
// 对路由变化作出响应...
}
}
2. vue2.2引入了 beforeRouteUpdate 守卫:
beforeRouteUpdate (to, from, next) {
// react to route changes...
// don't forget to call next()
}
4. 向路由组件传递参数-2:使用GET请求参数的形式,
1. 路由:{ path: '/user, component: User }
2. router-link :to="`/user?id=${msg.id}`">
3. 在路由组件User中获取GET参数:this.$route.query
5. 向路由组件传递参数-3:绑定属性
1. <router-view :msg="msg" /> -->传递变化参数msg(string)
2. <router-view msg="abc" /> -->传递固定的字符串'abc'
2. 在路由组件使用props声明接收的属性:props: { msg: String }
编程式路由导航
1. 路由组件对象中有一个控制路由的对象:$router,类似于window.location
2. 路由的实现:hash方式(h5之前),state(h5新推的方式)
1. hash方式:浏览器监听hash的变化,生成历史纪录;
1. vue的路由是hash的方式,获取hash:this.$route.hash
3. 路由组件中除了 $route 对象,还有一个操作路由导航的对象:$router
3. $router.push():相当于点击路由链接<router-link>,后退可以返回上一个路由;
1. this.$router.push('/home'); --->跳转向指定的路由
2. push('home') ->如果当前路由为:'/user',则跳转的新路由为:'/user/home'
3. push({ path: 'home' }) 等效于 push('home')
4. 在路由路径上传递参数:
$router.push({ name: 'user', params: { id: 12 }}) --> /user/12
router.push({ name: 'user', query: { id: '12' }}) --> /user?id=12
3. $router.replace():用新路由替换当前路由,与push()的区别是,后退不能返回;
1. 在浏览器中的历史记录中不会生成新的纪录,而是用新记录替换当前记录;
2. push()生成的历史记录是栈结构。
4. $router.back()/$router.go(-1):返回上一个路由;