当vue需要加载数据多或者网络慢时,加载数据时候会先出现vue模板(例如item.name),用户体验特别不好
解决方法有如下几种:
1、可以通过VUE内置的指令v-cloak解决这个问题(推荐) 具体实现:
CSS中添加样式
[v-cloak] {
display: none !important;
}
页面要渲染的额部分添加v-cloak
<ul v-cloak v-for="item in items">
<li>{{ item.name }}</li>
</ul>
2、可以在需要编译的元素前后加上
<template></template>
关于<template>
详解
不推荐第二种 在IE中不支持
<span>Message: {{ msg }}</span>
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html
指令:
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
data: {
num1: 10,
num2:2
},
computed: {
sum: function () {
return this.num1+this.num2;
}
}
如上 计算属性sum
的值就会为3
computed特点:
JS中:
var user_vue = new Vue({
el: ".user",
data: {
loginuser: {username:"我的名称比较长"}
},
filters: {
nameFilter(name) {
if (name.length > 4) {
name = name.substring(0, 4);
}
return name;
}
}
});
取值方式:
{{loginuser.username|nameFilter}}
v-bind:class="{ unclickable: page == 1 }"
<style type="text/css" scoped>
</style>
<button type="button" v-on:click="loginAction()">登录</button>
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
<li v-for="(item,index) in 10">{{item}}</li>
编历一个数字时item的值是从1 始的。 编历一个指定数字也就是相当编历一个从1到指定数字的数组。 所以上面这个例子的item是1-10,index是0-9
数据
data:{
items:[
{text:"第一组"},
{text:"第二组"},
{text:"第三组"},
]
}
页面
<li v-for="item in items">{{item.text}}</li>
<li v-for="(item, index) in items">
{{ index }} - {{ item.text }}
</li>
示例
Vue.component('zj-page', {
props: ["showpage", "currpage", "pages"],
computed: {
showPageArr: function () {
var halfshow = parseInt(this.showpage / 2);
var tempbegin = this.currpage - halfshow + 1;
var tempend = this.currpage + halfshow;
if (tempbegin < 1) {
tempend = tempend - tempbegin + 1;
tempbegin = 1;
if (tempend > this.pages) {
tempend = this.pages;
}
} else if (tempend > this.pages) {
tempbegin = this.pages - this.showpage + 1;
tempend = this.pages;
if (tempbegin < 1) {
tempbegin = 1;
}
}
var arr = [];
for (var i = tempbegin; i <= tempend; i++) {
arr.push(i);
}
return arr;
}
},
methods: {
num_click: function (num) {
this.$emit('gotopage', num, this.currpage);
},
last_click: function () {
if (this.currpage > 1) {
this.$emit('gotopage', this.currpage - 1, this.currpage);
}
},
next_click: function () {
if (this.currpage < this.pages) {
this.$emit('gotopage', this.currpage + 1, this.currpage);
}
},
begin_click: function () {
this.$emit('gotopage', 1, this.currpage);
},
end_click: function () {
this.$emit('gotopage', this.pages, this.currpage);
}
},
template: `
<div class="paging">
<span class="first_page" v-bind:class="{ unclickable: currpage == 1 }" v-on:click="begin_click()">首页</span>
<span class="prev_page" v-bind:class="{ unclickable: currpage == 1 }" v-on:click="last_click()">上一页</span>
<span v-bind:class="{ pitch_on: item == currpage }" class="pagination" v-for="(item,index) in showPageArr" v-on:click="num_click(item)">{{ item }} </span>
<span class="next_page" v-bind:class="{ unclickable: currpage == pages||pages == 0 }" v-on:click="next_click()">下一页</span>
<span class="last_page" v-bind:class="{ unclickable: currpage == pages||pages == 0}" v-on:click="end_click()">末页</span>
</div>
`
});
使用方法
<zj-page v-bind:showpage="showpage" v-bind:currpage="currpage" v-bind:pages="pages" v-on:gotopage="gotopage"></zj-page>
JS代码
new Vue({
el: ".prepare_main",
data: {
showpage: 10,
currpage: 1,
pages: 20
},
methods: {
gotopage: function (newpage, oldpage) {
console.info("跳转到:" + newpage + " 原页:" + oldpage);
}
}
});
注意:在分页组件内部,点击页数后 并没有直接在自定义组件内修改当前页数,而是发送了一个事件,让父组件来更新页数, 是因为Vue的属性传递是
单向
的
子组件中定义
props: ["showpage", "currpage", "pages"]
父组件中传递
v-bind:showpage="showpage"
子组件中调用
this.$emit('gotopage', newValue, oldValue);
父组件中传递
v-on:gotopage="gotopage"
事件定义
var event = new Vue()
发送事件
event.$emit('load_paper_detail',data);
接受事件
event.$on("load_paper_detail", function (data) {
_this.load_paper_detail();
})
beforeCreate
在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
created
实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount
在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted
el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。 Ajax请求数据在此阶段
beforeUpdate
数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
updated
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。 当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。 该钩子在服务器端渲染期间不被调用。
beforeDestroy
实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
nextTick
方法,意思是在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
this.$nextTick(function(){
});
扩展
Vue.prototype.common = {
abc:function(){
}
}
调用
this.common.abc();
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
调用
{{ message | capitalize }}
过滤器可以串联:
{{ message | filterA | filterB }}
utils.js
export const arrayContain = function (array, obj){
for (var i = 0; i < array.length; i++){
if (array[i] == obj){//如果要求数据类型也一致,这里可使用恒等号===
return true;
}
}
return false;
}
如果想引用这个方法,就通过import引入
import {arrayContain} from '../../js/utils';
在vue文件中的<style>
内填写需要引用的文件
如:
@import "./css/index.css";
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
},
getters: {
m_num: state => {
return state.count+1;
}
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
state 就类似于 data 用来保存状态的
加工处理状态的数据 返回新数据
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
store.commit('increment')
附带参数
mutations: {
increment (state, n) {
state.count += n
}
}
调用方式
store.commit('increment', 10)
类似这样
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
对象方式提交
store.commit({
type: 'increment',
amount: 10
})
Action 类似于 mutation,不同在于:
Action 通过 store.dispatch
方法触发:
store.dispatch('increment')