vue的安装
- 安装node.js
- 安装npm:
npm install -g cnpm --registry=https://registry.npm.taobao.org
- 使用cnpm安装vue:
cnpm install vue -g
- 安装vue命令行工具:
cnpm install vue-cli -g
- 安装vue-devtools调试工具:
- 创建vue脚手架:
vue init webpack myproject
vue init webpack myproject
cd myproject // 进入目录
cnpm install // 安装依赖
cnpm run dev // 开启服务
- src 主开发目录,所有的单文件组件都会放在这个目录下 - static 项目静态目录,所有的css、js都会放在这个文件夹下 - dist 项目打包发布文件夹,最后要上线单文件夹项目都在这个文件夹中 - node_modules node的包目录 - config 配置目录 - build 项目打包时依赖的目录
- 常用命令
- v-html:将内容按照html格式进行插入
- v-text:将内容按照文本格式进行插入,但会覆盖原有标签内的内容,不会有加载的闪烁问题
- v-cloak:解决加载时的闪烁问题
- 绑定属性:v-bind 或者 直接写 冒号 如果我们需要设置的模板变量是一个属性,比如a标签的href属性
- 绑定事件:v-on 或者 @ 符号:给元素绑定对应事件。
- 表单绑定 v-model:
- 动态绑定
当某些情况下,无法确定表单中所代表的属性值,可以使用v-bind进行动态绑定,v-> model获取到的表单输入 此时则是我们定义的v-bind属性值
- v-if 指令用于条件性的渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候渲染
- 与v-if不同的是: v-show 的元素始终会被渲染并保留在 DOM 中 v-show 只是简单地切换元素的 CSS 属性 display
- Vue实例生命周期
- beforeCreate 数据还没有监听,没有绑定到vue对象实例,同时也没有挂载对象
- created 数据已经绑定到了对象实例,但是还没有挂载对象
- beforeMount 模板已经编译好了,根据数据和模板已经生成了对应的元素对象,将数据对象关联到了对象的 $el属性
---------------------------------------------------------------------
$el属性是一个HTMLElement对象,也就是这个阶段,vue实例通过原生的createElement等方法来创建这个html片段, 准备注入到我们vue实例指明的el属性所对应的挂载点 --------------------------------------------------------------------------
- mounted 将$el的内容挂载到了el,相当于我们在jQuery执行了$(el).html($el),生成页面上真正的dom
-------------------------------------------------------
上面我们就会发现页面的元素和我们$el的元素是一致的。在此之后,我们能够用方法来获取到el元素下的dom对象,并进 行各种操作 ----------------------------------------------------------------------------
- beforeUpdate 数据发生变化时调用
- updated 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子
- beforeDestroy Vue实例销毁前 - destroyed Vue实例销毁后
- 过滤器
{{ 0 | myfilter }}
//过滤器
filters: {
myfilter: function (value) {
if(value==1){
return '已支付';
}else{
return '未支付';
}
}
},
- 子组件
components: {
// 'mh_test':mh_test
},
- 计算属性
data () {
return {
message:'hello world 你好',
},
//计算属性
computed:{
reverse_message:function(){
return this.message.split('').reverse().join('')
}
},
- 监听属性
//监听属性
watch : {
kilometers:function(val) {
this.kilometers = val;
this.meters = this.kilometers * 1000
},
meters : function (val) {
this.kilometers = val/ 1000;
this.meters = val;
}
},
- 函数
data () {
return {
datalist:[],
},
totalCount : function(){
var total = 0;
for (var i = 0,l = this.datalist.length;i<l;i++) {
total+=this.datalist[i].num;
}
return total;
},
- 样式
<style>
.on {
background: #cdcbff;
}
.off {
background: #fefdff;
}
</style>
一 路由拦截器
项目中,用户不登录只能去登录页面,不可以访问别的页面,这种情况的话,可以用路由拦截器
- 先说下区分下route与router
- route:相当于当前正在跳转的路由对象。可以从里面获取name,path,params,query等。
如取路由带来的参数:this.$route.params - router:VueRouter的实例,相当于一个全局的路由器对象,里面含有很多属性和子对象,例如history对象。。。经常用的跳转链接就可以用this.$router.push,和router-link跳转一样
//带参数路由跳转
this.$router.push({path:'/home',params:{id:123}})
//取参数
this.$route.params.id //123
- 言归正传说路由拦截
//路由拦截器
//to为向后走的路由对象,包括路由的完整信息
//from为从哪跳来的路由对象
//next()控制路由向下走,重新定义路由跳转的路由next(‘路由路径)
/** 验证用户是否登录 **/
router.beforeEach((to,from,next) => {
if(to.matched.some( m => m.meta.auth)) {
// console.log("先判断是否登录");
if(to.name=='Login'){
next();
}else{
if(localStorage.getItem('token')){
//访问服务器缓存数据,判断当前token是否失效
Vue.http.get("http:xxxx/Login/UserIsLogin?token="+localStorage.getItem('token')+"&url="+to.name,{withCredentials: true}).then(response => response.json()).then(num => {
// console.log('是否登录',num);
if(num.code==1001){
next();
}else{
alert('您的token已超时,请重新登录');
next('/Login');
}
})
}else{
next('/Login');
}
}
} else {
console.log("请先登录");
next()
}
})
//或者简洁的可以:
router.beforeEach((to,from,next)=>{
if(localStorage.getItem('token')||to.name=='login'){
next()
}else{
//如果没有token值,则跳到登录页面
next({path:'/login'})
}
next()
})
二 请求拦截
统一处理错误及配置请求信息
- 安装 axios , 命令: npm install axios --save-dev
- 在根目录的config目录下新建文件 axios.js ,内容如下:
import axios from ‘axios’
// 配置默认的host,假如你的API host是:http://api.htmlx.club
axios.defaults.baseURL = ‘http://api.htmlx.club’
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error)
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error)
});
请求拦截 根据自己的需求加对应的代码
三、父子组件传参
- 父组件
<template>
<div>
<h1>hello</h1>
<v-child :msg='msg' @cmsg="cmsg"></v-child>
{{childmsg}}
</div>
</template>
<script>
import child from '@/components/child'
export default {
name:'parent',
data:function(){
return {
'msg': 'hello everybody',
childmsg: ''
}
},
methods:{
cmsg:function(obj){
this.childmsg =obj
}
}
,
components:{
'v-child': child
}
}
</script>
- 子组件
<template>
<div>
{{msg}}
<button @click="toparent">传值到父组件</button>
</div>
</template>
<script>
export default {
name:'child',
data:function(){
return {
}
},
methods:{
toparent:function(){
this.$emit("cmsg", "来自子组件的数据")
}
}
,
props:['msg']
}
</script>
四、Vuex状态管理
- 使用场景:大型项目
- 安装:
cnpm install --save vuex
- 使用:
import Vue from 'vue' import App from './App' import router from './router' import axios from 'axios' import Vuex from 'vuex' Vue.config.productionTip = false Vue.prototype.axios = axios Vue.use(Vuex); // vuex的配置 const store = new Vuex.Store({ }); /* eslint-disable no-new */ new Vue({ el: '#app', router, // 使用vuex.任何组件使用同一个store的数据时,只要store的数据变化,对应的组件也会更新。 store: store, components: { App }, template: '<App/>', })
- 任何组件使用同一个store的数据时,只要store的数据变化,对应的组件也会更新。
- 数据保存在vuex的state字段内。
// vuex的配置 const store = new Vuex.Store({ state:{ // 计数器。在任何组件内,可以直接通过$store.state.count读取 count: 0 } });
- 可以直接通过$route.state.count读取。也可以用一个计算属性来显示
<template> <div> {{ $store.state.count }} <br> {{ count }} </div> </template> <script> export default { name: "x1", computed:{ count: function () { // 通过计算属性显示 return this.$store.state.count; } } } </script>
- store的数据只能读取,不能手动修改。改变方式是:定义mutations.
- 在组件内,通过this.#store.commit()方法来执行在mutations中定义的函数。
- mutations可以接受第二个参数。
// vuex的配置 const store = new Vuex.Store({ state:{ // 计数器。在任何组件内,可以直接通过$store.state.count读取 count: 0 }, mutations:{ increment(state){ state.count++; }, // ES6: n=1是当参数没有传值时,使用的默认值 // 当一个参数不够用时,可以传入一个对象 decrement(state, n=1){ state.count-=n; } } });
{{ count }} <br> <button v-on:click="handlIncrement">+1</button> <button v-on:click="handlDecrement">-2</button> methods:{ handlIncrement:function () { this.$store.commit("increment"); }, handlDecrement:function () { this.$store.commit('decrement', 2) } }
- 提交mutation的另一种方式是直接使用包含type属性的对象。比如:
// vuex的配置 const store = new Vuex.Store({ state:{ // 计数器。在任何组件内,可以直接通过$store.state.count读取 count: 0 }, mutations:{ increment(state, params){ state.count+= params.count; } } });
methods:{ handlIncrement:function () { // this.$store.commit("increment"); this.$store.commit({ type:'increment', count: 10 }) } }
高级用法。getters、actions、modules
- 仅仅获取小于10的数字。常规用法
// main.js
// vuex的配置
const store = new Vuex.Store({
state:{
list: [1, 5, 8, 10, 30, 50]
},
mutations:{
}
});
<template>
<div>
<h3>vuex高级用法</h3>
<li v-for="i in list">{{i}}</li>
</div>
</template>
<script>
export default {
name: "vuex2",
computed:{
list:function () {
// 过滤数组,仅仅显示小于10的数字
return this.$store.state.list.filter(item => item < 10);
}
}
}
</script>
<style scoped>
</style>
- getters的使用
const store = new Vuex.Store({
state:{
count++,
list: [1, 5, 8, 10, 30, 50]
},
getters:{
filterList:state=>{
return state.list.filter(item => item < 10);
},
listCount:function (state, getters) {
// getters的依赖,一个getters可以依赖于另一个getters
return getters.filterList.length;
}
}
,
mutations:{
increments(state){
state.count++;
}
}
});
- actions的使用
- 多此一举的操作。actions中
context.commit('increment', {count: 2});
。vue组件中this.$store.dispatch('increment')
- 多此一举的操作。actions中
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'
import Vuex from 'vuex'
Vue.config.productionTip = false
Vue.prototype.axios = axios
Vue.use(Vuex);
// vuex的配置
const store = new Vuex.Store({
state:{
// 计数器。在任何组件内,可以直接通过$store.state.count读取
count: 0,
list: [1, 5, 8, 10, 30, 50]
},
getters:{
filterList:state=>{
return state.list.filter(item => item < 10);
},
listCount:function (state, getters) {
// getters的依赖
return getters.filterList.length;
}
}
,
mutations:{
increment(state, params){
state.count+= params.count;
},
decrement(state, n=1){
state.count-=n;
}
},
actions:{
increment(context){
context.commit('increment', {count: 2});
}
}
});
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
// 使用vuex.任何组件使用同一个store的数据时,只要store的数据变化,对应的组件也会更新。
store: store,
components: { App },
template: '<App/>',
})
<template>
<div>
<h3>vuex高级用法</h3>
{{listCount}}
<li v-for="i in list">{{i}}</li>
<br>
{{this.$store.state.count}}
<br>
<button v-on:click="handleActionIncrement">+2</button>
</div>
</template>
<script>
export default {
name: "vuex2",
methods:{
handleActionIncrement:function () {
this.$store.dispatch('increment');
}
},
computed:{
list:function () {
// 过滤数组,仅仅显示小于10的数字
// return this.$store.state.list.filter(item => item < 10);
return this.$store.getters.filterList;
},
listCount:function () {
return this.$store.getters.listCount;
},
}
}
</script>
<style scoped>
</style>
- module将一个store分割到不同的模块。
const moduleA = {
state:{
msg: 'moduleA'
},
mutations:{},
actions:{},
getters:{}
};
const moduleB = {
state:{
msg: 'moduleB'
},
mutations:{},
actions:{},
getters:{}
};
// vuex的配置
const store = new Vuex.Store({
state:{
// 计数器。在任何组件内,可以直接通过$store.state.count读取
count: 0,
list: [1, 5, 8, 10, 30, 50],
a: moduleA,
b: moduleB
},
getters:{
filterList:state=>{
return state.list.filter(item => item < 10);
},
listCount:function (state, getters) {
// getters的依赖
return getters.filterList.length;
}
}
,
mutations:{
},
actions:{
}
});