这里对自己学习技术胖vue2.x的部分过程做出记录。
1.v-if和v-show区别
v-if:判断是否加载dom点
优点:减轻了服务器的压力
v-show:判断是否展示,调整了css的display属性
优点:使客户端操作更加流畅
2.v-text和v-html
①使用场景:
v-text:{{xxx}}有一定的弊端,当js代码出错的时候会显示出源码,v-text,就是解决这个问题的。
<span>{{ message }}</span>
等同于<span v-text="message"></span>
v-html:当内容含有html标签的时候v-text无法解析,此时需要使用v-html。涉及到起安全性问题以及使用场景,在生产环境中动态渲染HTML是非常危险的,因为容易导致XSS攻击。所以只能在可信的内容上使用v-html,永远不要在用户提交和可操作的网页上使用。
ps:cookie安全策略
在服务器端设置cookie的时候设置 http-only, 这样就可以防止用户通过JS获取cookie。对cookie的读写或发送一般有如下字段进行设置:
http-only: 只允许http或https请求读取cookie、JS代码是无法读取cookie的(document.cookie会显示http-only的cookie项被自动过滤掉)。发送请求时自动发送cookie.
使用方法:response.setHeader( "Set-Cookie" , "cookiename=httponlyTest;Path=/;Domain=domainvalue;Max-Age=seconds;HTTPOnly");
secure-only: 只允许https请求读取,发送请求时自动发送cookie。
host-only: 只允许主机域名与domain设置完成一致的网站才能访问该cookie。
3.内部指令(v-pre、v-clock 、v-once)
v-pre:跳过编译,以{{xxx}}的形式展现在页面上
v-cloak:和css配合使用,渲染完指定的整个dom再显示
css:
[v-cloak] {
display: none;
}
html/template:
<div v-cloak>
{{message}}
</div>
v-once:指定部分只渲染一次,再渲染时为静态,不参与之后的渲染,在静态内容很多的页面能明显提高页面渲染效率,但是需要在编程前提前计算好哪些是只渲染一次的元素。
4.自定义指令Vue.directive
<div id="app">
<span v-jcolor="color">{{num}}</span>
</div>
<script type="text/javascript">
Vue.directive('jcolor', function (el, binding, vnode) {
el.style = 'color:' + binding.value;
});
var app = new Vue({
el: "#app",
data: {
num: 10,
color: "green"
}
})
</script>
自定义指令三个重要参数:
el: 指令所绑定的元素,可以用来直接操作DOM。
-
binding: 一个对象,包含指令的很多信息。
vnode: Vue编译生成的虚拟节点。
5.Vue.set(绑定在Vue的构造函数上)/this.$set(绑定在Vue的原型上)
存在意义:
由于js的限制,无法检测以以下两种情况动态变化的数组:
①通过索引改变数组某项变化的值得情况
②改变数组长度的情况
使用场景:
<div id="app">
<ul>
<li v-for=" aa in arr">{{aa}}</li>
</ul>
<button @click="add()">外部添加</button>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data() {
return {
arr : ['aaa', 'bbb', 'ccc']
}
},
methods: {
add() {
console.log("我已经执行了");
this.arr[1] = 'ddd';//情况①,通过数组索引改变值
this.arr.length = 2;//情况②,改变数组长度
// Vue.set(this.arr,1,'ddd');//情况①解决方案通过set实现/replace
// this.arr.splice(2);//情况②通过splice直接增删数组,改变数组长度
}
}
})
</script>
这里有一个现象:如果这里放开赋值的注释,将arr[1]set为'ddd',前面的
this.arr.length = 2
也会生效,这里涉及到Vue.set的实现原理,留下问题,日后研究。
6.delimiters
有时用到其他系统自带标签也为{{}},vue默认{{}}插值,产生冲突,此时就需要用delimiters修改插值符号,数组形式,一前一后,如:delimiters:['${','}']
此时插值符号为${}
7.vue-router
(1)带参数
①params传参(通过<router-link> 标签中的to传参 )
父组件中:
<router-link :to="{name:xxx,params:{username:'test'}}">valueString</router-link>
子组件中
通过{{$route.params.username}}
直接获取
②url传参(router/index.js中配置)
在router/index.js文件中:
export default new Router({
routes: [
{
path: '/',
component: Hello
},{
path:'/params/:newsId(\\d+)/:newsTitle',
component:Params//带参数(拼接url且newsId为整数)
}
]
})
在Params组件中:
{{$route.params.newsId}}
/{{$route.params.newsTitle}}
可取到相应值
(2)重定向(redirect、alias两种方法)
export default new Router({
routes: [
{
path: '/',
component: Hello
},{
path:'/goback',
redirect:'/'//重定向改变url
},{
path:'/goParams/:newsId(\\d+)/:newsTitle',
redirect:'/params/:newsId(\\d+)/:newsTitle'//重定向时传参
},{
path: '/hi1',
component: Hi1,
alias:'/bieming'
//别名,配合<router-link to="/bieming">重定向</router-link>使用,重定向不改变url只改变router-view,更 加友好,但是不支持path为'/'的情况
}
]
})
(3)路由加动画过渡效果
①给过渡效果标签:name、mode(非必须)
mode:
- in-out:新元素先进入过渡,完成之后当前元素过渡离开。
- out-in:当前元素先进行过渡离开,离开完成后新元素过渡进入。
<transition name="fade" mode="out-in">
<router-view ></router-view>
</transition>
②给过渡效果定义css样式
name:
fade-enter:进入过渡的开始状态,元素被插入时生效,只应用一帧后立刻删除。
fade-enter-active:进入过渡的结束状态,元素被插入时就生效,在过渡过程完成后移除。
fade-leave:离开过渡的开始状态,元素被删除时触发,只应用一帧后立刻删除。
fade-leave-active:离开过渡的结束状态,元素被删除时生效,离开过渡完成后被删除。
eg:透明动画过渡效果
.fade-enter {
opacity:0;
}
.fade-leave{
opacity:1;
}
.fade-enter-active{
transition:opacity .5s;
}
.fade-leave-active{
opacity:0;
transition:opacity .5s;
}
(4)路由mode设置以及404页面设置
①mode:包括history和hash两种,两者区别即url上是否有#
,history无#,比较美观,推荐使用。
export default new Router({
mode: 'history',
routes: [
{
path: '/',
component: Hello
}
]
})
②404页面配置
如果用户在url上输入的页面不存在,前端做出处理即显示404页面,给用户以提示,对用户更加友好。
实现方式:
第一步:在router/index.js文件下给出未配置路由(即不存在url)的情况
{
path:'*',
component:Error
}
第二步:写error组件,当访问到页面不存在时显示该页面
(5)路由钩子
两种位置可以使用:
①router/index.js
路由中仅可以使用beforeEnter。
eg:
{
path: '/testGouzi',
name: 'TestGouzi',
component: TestGouzi,
beforeEnter: (to, from, next) => {
console.log('to', to);
console.log('from', from);
next();
}
②要对离开或进入该路由进行判断的组件中。
eg:
export default {
name: "HelloWorld1",
data() {
return {};
},
beforeRouteEnter: (to, from, next) => {
alert("我进来了1");
next();
},
beforeRouteLeave: (to, from, next) => {
alert("我走了1");
next();
},
};
(6)编程式导航
①返回上一级:this.$router.go(-1);
②返回下一级:this.$router.go(1);
③跳转到某页面(此例为跳转为home页):this.$router.push('/');
ps:在使用push进行路由跳转的时候存在一个问题,即在一个页面重复调用该函数会报如下错误:
解决方案:在router/index.js中对Router原型上的push进行处理,此种方法事实上只是将报错catch,使之不在控制台飘红报错。
import Router from 'vue-router'
Vue.use(Router)
//获取原型对象上的push函数
const originalPush = Router.prototype.push
//修改原型对象中的push方法
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
④带参数跳转
this.$router.push({ path: "/", query: { msg: "我带着path的参数query回家啦" } });
this.$router.push({ name: "HelloWorld", query: { msg: "我带着不太规范的name的query参数回家啦" } });
this.$router.push({ name: "HelloWorld", params: { msg: "我带着参数params回家啦" } });
以上三种写法均可行,query带参数会体现在url上,params不会,params传参仅可用name指向路由。
8.vuex
vuex的使用主要需要掌握以下5点:
- state访问状态
- mutations修改状态
- getters计算过滤操作
- actions异步修改状态
- module模块组
准备工作
①利用npm安装vuex
npm install vuex --save
②建vuex文件夹,建store.js文件,并在文件中进行vuex引用
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
(1)state访问状态
需要引用vuex状态管理的组件,这里统一叫做count.vue。
①store.js
const state = {
count: 1
}
export default new Vuex.Store({
state
})
②count.vue(共有3种方法可以取state)
<template>
<div>
<!--state 法一 -->
<!-- <h3>{{ $store.state.count }}</h3> -->
<!-- 法二 computed返回的count/法三 (写法1、2)mapstate-->
<h3>{{ count }}</h3>
</div>
</template>
<script>
import store from '@/vuex/store'
export default{
data(){
return{
}
},
// 法二
// computed: {
// count() {
// return this.$store.state.count;
// },
// },
// 法三 mapstate 写法一箭头函数
// computed: mapState({
// count: (state) => state.count,
// }),
// 法三 mapstate 写法二数组
computed: mapState(["count"]),
store
}
</script>
(2)mutations修改状态
Vuex提供commit方法来修改状态:$store.commit( )
①store.js
const mutations = {
// 传参
add(state, n) {
state.count += n;
},
reduce(state) {
state.count--;
}
}
export default new Vuex.Store({
state,mutations
})
②count.vue(两种方法)
<template>
<div>
<!--mutations 法一 -->
<!-- <button @click="$store.commit('add', 10)">+</button> -->
<!-- <button @click="$store.commit('reduce')">-</button> -->
<!-- mutations 法二 -->
<button @click="reduce">-</button>
</div>
</template>
<script>
import store from "@/vuex/store";
// 这里注意一定要加大括号
import { mapMutations, mapState } from "vuex";
export default {
data() {
return {
};
},
//由于vue构造器里面只能有一个methods属性所以用对象展开符对其进行修改
// mutations 法二
methods: {
...mapMutations(["reduce"]),
}
},
store,
};
</script>
(3)getters计算过滤操作
这里以在它输出前+100作为操作示例,下图为刚进入页面时的效果,已知$store.state.count初始值为1,可见其刚开始进入页面的时候就执行了getters+100的操作,可通过点击加减按钮看到getters的处理。
①store.js
const getters = {
count: function (state) {
return state.count += 100;
}
}
export default new Vuex.Store({
state,getters
})
②count.vue(两种方法)
<template>
<div>
<h3>{{ count }}</h3>
<div>
<button @click="$store.commit('add', 10)">+</button>
<button @click="$store.commit('reduce')">-</button>
</div>
</div>
</template>
<script>
import store from "@/vuex/store";
// 这里注意一定要加大括号
import { mapState, mapGetters } from "vuex";
export default {
data() {
return {
};
},
computed: {
// ...mapState(["count"]),
// getters 法一
// count() {
// return this.$store.getters.count
// }
// getters 法二 mapGetters
...mapGetters(["count"]),
},
store,
};
</script>
(4)actions异步修改状态
此块存在的灵魂在于异步,所以这里使用setTimeout进行异步操作,这里点击add执行的顺序应是先加10,两秒后再减1,控制台输出文字的顺序应该在count减一之前。
①store.js(两种写法)
const actions = {
// context上下文/commit对象作为参数两种写法
addActions(context) {
console.log(context);
context.commit('add', 10);
// 异步看看
setTimeout(() => { context.commit('reduce') }, 2000)
console.log('我比异步那个先执行了')
},
reduceActions({ commit }) {
commit('reduce')
}
}
②count.vue
触发组件中addActions方法来感受异步。
<template>
<div>
<h3>{{ count }}</h3>
<p>异步看看</p>
<p>
<button @click="addActions">+</button>
<button @click="reduceActions">-</button>
</p>
</div>
</template>
<script>
import store from "@/vuex/store";
import { mapState,mapActions } from "vuex";
export default {
data() {
return {
};
},
methods: {
// actions
...mapActions(["addActions", "reduceActions"]),
},
computed: {
...mapState(["count"]),
},
store,
};
</script>
(5)module模块组
建议在项目比较复杂的情况用module模块
①store.js
const moduleA={ state,mutations,getters,actions}
export default new Vuex.Store({
modules:{a:moduleA}
})
②count.vue(两种引用方法)
<!-- 法一 -->
<h3>{{$store.state.a.count}}</h3>
<!-- 法二 -->
computed:{
count(){
return this.$store.state.a.count;
}
},