第11章:组件详解

组件是Vue.js最推崇也最强大的功能之一,核心目标是可重用性。

我们把组件代码按照template、style、script的拆分方式,放置到对应的.vue文件中。

1.注册

Vue.js的组件注册分为全局注册和局部注册。

全局注册使用Vue.component方法。第一个参数是组件名字,第二个参数是组件的构造函数,要么是function,要么是object。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<didi-component></didi-component>
<en-component></en-component>
</div>
<script src="js/vue.js"></script>
<script>
//第二个参数传入object的情况
Vue.component("didi-component",{
template:"<div>A custom component!</div>"
});
//第二个参数传入function的情况,它是一个组件构造器
var ENcomponent=Vue.extend({
template:"<div>A 2rd components</div>"
});
//注册
Vue.component("en-component",ENcomponent);
//创建根实例
new Vue({
el:"#app"
})
</script>
</body>
</html>

显示效果

局部注册,以vue实例选项components或者组件构造器即Vue.extend函数的components选项。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<didi-component></didi-component>
</div>
<script src="js/vue.js"></script>
<script>
var Parent=Vue.extend({
template:"<p>这里是父组件的内容</p><br/><child></child>",
components:{
"child":{
template:"<div>我是子组件的内容</div>"
}
}
})
new Vue({
el:"#app",
components:{
"didi-component":Parent
}
})
</script>
</body>
</html>

显示效果

2.数据传递

组件作为一个app(项目)的组成部分,总是要涉及到组件通信。组件通信属于数据传递的范畴,数据传递一共有3种方式:

props、组件通信、slot。

(1)props属性

首先区别一下props和data和propsData。props作用于父子组件之间的数据传递,data组件或者vue实例化时经常使用,propsData用来在组件初始化后覆盖props中的属性。接下来是如何使用props属性。

第一种方式,字面量语法

直接在组件的html代码中传入普通的字符串,在组件内部使用props属性。注意:html不区分大小写,名字为camelCase的属性会转化为短横线隔开(kebab-case)。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<hello-component msg="hello"></hello-component>
<vivian my-data="3.1415"></vivian>
</div>
<script src="js/vue.js"></script>
<script>
Vue.component("hello-component",{
props:["msg"],
template:"<span>{{msg}},front-end!</span>"
});
Vue.component("vivian",{
props:["myData"],
template:"<div>{{myData}}</div>",
replace:true
})
new Vue({
el:"#app"
})
</script>
</body>
</html>

第二种,动态语法

下面的例子从父组件向子组件传递属性,每当父组件的数据变化时,该变化也会传导给子组件。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<vivi-props></vivi-props>
</div>
<script src="js/vue.js"></script>
<script>
var Child=Vue.extend({
props:["viviProps"],
//传给子组件的属性名称
template:"<div>{{viviProps}}</div>",
//既然在props属性上定义了,那么就可以在模板里使用了
replace:true
});
var Parent=Vue.extend({
template:"<p>我是父组件的内容</p><br/><child :vivi-props='hello'></child>",
data:function(){
return {"hello":"hello"}
},
//动态绑定的属性的值由父组件的data来定义
components:{
"child":Child
}
})
new Vue({
el:"#app",
components:{
"vivi-props":Parent
}
});
</script>
</body>
</html>

第三种方式,使用.sync和.once修饰符。

默认或者使用.once修饰符是父组件到子组件的单向绑定。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model="info.name"/>
<child v-bind:msg.once="info"></child>
<!--把根实例的info数据属性传递给子组件child的msg属性-->
</div>
<script src="js/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
info:{
name:"顺风车"
}
},
components:{
"child":{
props:["msg"],
template:"<div>{{msg.name}}</div>"
}
}
})
</script>
</body>
</html>

.sync修饰符能做到双向绑定。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
父组件:
<input v-model="val"><br/>
子组件:
<test :test.sync="val"></test>
</div>
<script src="js/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
val: 1
},
components: {
"test": {
props: ['test'],
template: "<input v-model='test'/>"
}
}
});
</script>
</body>
</html>

显示结果

第4种方式,prop验证。

我们把自己的组件给别人使用,那么要求使用者能够根据prop提供的对象正确使用。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
父组件:
<input v-model="val"><br/>
子组件:
<test :test="val"></test>
</div>
<script src="js/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
val: 1
},
components:{
test:{
props: {
test: {
twoWay: true
}
//我们希望组件的使用者通过双向绑定来使用这个组件。
},
//把根实例的val属性传递给test属性。
template: "<input v-model='test'/>"
}
}
});
</script>
</body>
</html>

我们看到这个代码 <test :test="val"></test> 会抛出错误如下:

那么正确的使用应该是如下,加上.sync修饰词,以满足twoWay:true的要求。

第5种方式,prop转换函数,coerce函数。可以理解为prop属性值的过滤器。

(2)组件通信

尽管this.$parent和this.$children(属性)可以访问父/子组件的数据,根实例的后代可以通过this.$root访问根实例,但这种方式应该尽量避免。

首先,因为父子组件紧密的耦合,只看父组件却很难理解父组件的状态,因为它能被任意的修改。再次,子组件要使用父组件的数据,应当避免直接依赖,尽量显式的使用props属性。

我们的方案是通过作用域传递事件。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<template id="child-template">
<input v-model="msg">
<button v-on:click="notify">Dispatch Event</button>
<!--子组件绑定了notify函数-->
</template>
<div id="events-example">
<p>Message:{{messages|json}}</p>
<child></child>
</div>
</div>
<script src="js/vue.js"></script>
<script>
Vue.component("child",{
template:"#child-template",
data:function(){
return {msg:"hello"}
},
methods:{
notify:function(){
if(this.msg.trim()){
this.$dispatch("child-msg",this.msg);
this.msg="";
}
//notify函数的功能是把msg属性的值dispatch到child-msg事件上,它会沿着父作用域的链冒泡
}
}
});
var parent=new Vue({
el:"#events-example",
data:{
messages:[]
},
events:{
"child-msg":function(msg){
this.messages.push(msg);
}
//接收到child-msg事件后,那么执行push方法
}
})
var vm = new Vue({
el: '#app'
});
</script>
</body>
</html>

接下来是在子组件v-on监听,更加简洁的代码。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<template id="child-template">
<input v-model="msg">
<button v-on:click="notify">Dispatch Event</button>
<!--子组件绑定了notify函数-->
</template>
<div id="events-example">
<p>Message:{{messages|json}}</p>
<child v-on:child-msg="handleIt"></child>
</div>
</div>
<script src="js/vue.js"></script>
<script>
Vue.component("child",{
template:"#child-template",
data:function(){
return {msg:"hello"}
},
methods:{
notify:function(){
if(this.msg.trim()){
this.$dispatch("child-msg",this.msg);
this.msg=""; //notify函数的功能是把msg属性的值dispatch,触发child-msg事件,它会沿着父作用域的链冒泡
}
}
});
var parent=new Vue({
el:"#events-example",
data:{
messages:[]
},
//改动后的代码
methods:{
handleIt:function(msg){
this.messages.push(msg);
}
}
})
var vm = new Vue({
el: '#app'
});
</script>
</body>
</html>

有时js中直接访问子组件,可用v-ref为子组件指定一个索引ID。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div id="events-example">
<p>Message:{{messages|json}}</p>
<button @click="handleIt">打印msg字符串儿</button>
<!--点击按钮,那么执行handleIt方法-->
<child v-ref:id1></child>
</div>
</div>
<script src="js/vue.js"></script>
<script>
Vue.component("child",{
template:"<div>{{msg}}</div>",
data:function(){
return {msg:"hello"}
}
});
var parent=new Vue({
el:"#events-example",
data:{
messages:[]
},
//改动后的代码
methods:{
handleIt:function(){
console.log(this.$refs.id1.msg);
//那么就可以直接通过id名访问到子组件的属性了
}
}
})
var vm = new Vue({
el: '#app'
});
</script>
</body>
</html> </body>
</html>

(3)slot分发内容

组合组件时,内容分发API是非常有用的机制。

<vivi>
<vivi-header></vivi-header>
<vivi-footer></vivi-footer>
</vivi>

首先,明确分发内容的作用域。

<child v-on:child-msg="handleIt">{{msg}}</child>

msg绑定到父组件的数据还是子组件的数据里?答案是父组件。因为父组件模板的内容在父组件的作用域里编译,子组件模板的内容在子组件的作用域里编译。

所以对于分发内容(接下来就知道什么是分发内容了), 在父组件内容里编译。

接下来看,单个slot。

当子组件模板里只有一个没有任何修饰的Slot,那么父组件的整个内容将插入到slot的挂载点并替换掉它。

单个slot的DEMO:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<template id="viviTemplate">
<div>
<h1>这里是vivi组件的内容</h1>
<slot>
如果没有分发内容,则显示我
</slot>
<!--回退内容,当宿主元素为空没有内容插入时-->
</div>
</template>
<div id="app">
<vivi-component>
<p>这里是原始内容</p>
<p>这里是更多的原始内容</p>
<!--很明显,这里的p标签的作用域并不是vivi-component的内容,而是它的父组件的内容-->
</vivi-component>
</div>
<script src="js/vue.js"></script>
<script>
Vue.component("vivi-component",{
template:"#viviTemplate",
})
var vm = new Vue({
el: '#app'
});
</script>
</body>
</html> </body>
</html>

显示效果:

接下来看,命名的slot的用法。

<slot>元素可使用name配置如何分发内容。仍然可以有一个匿名的slot,作为找不到匹配内容片段的回退容器。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<template id="multiTemplate">
<div>
<slot name="one"></slot>
<slot></slot>
<slot name="two"></slot>
</div>
</template>
<div id="app">
<multi-insertion> <p slot="one">One</p>
<!--对应name值为one的被分发内容-->
<p slot="two">Two</p>
<!--对应name值为two的被分发的内容-->
<p>Default A</p>
<p slot="three"></p>
<!--对应默认的被分发的内容--> </multi-insertion>
</div>
<script src="js/vue.js"></script>
<script>
Vue.component("multi-insertion",{
template:"#multiTemplate",
})
var vm = new Vue({
el: '#app'
});
</script>
</body>
</html> </body>
</html>

显示结果:

最后分析一下,源码。

SLOT的源码如下:

var slot = {

    priority: SLOT,//优先级
params: ['name'],//
//bind方法的功能是绑定指令
bind: function bind() { var name = this.params.name || 'default'; var content = this.vm._slotContents && this.vm._slotContents[name]; if (!content || !content.hasChildNodes()) { this.fallback();
} else {
this.compile(content.cloneNode(true), this.vm._context, this.vm); }
}, compile: function compile(content, context, host) {
//
if (content && context) {

if (this.el.hasChildNodes() && content.childNodes.length === 1 && content.childNodes[0].nodeType === 1 &&
//对v-if指令的处理,略。
content.childNodes[0].hasAttribute('v-if')) { var elseBlock = document.createElement('template');
elseBlock.setAttribute('v-else', '');
elseBlock.innerHTML = this.el.innerHTML;
elseBlock._context = this.vm;
content.appendChild(elseBlock);
}
var scope = host ? host._scope : this._scope; this.unlink = context.$compile(content, host, scope, this._frag); }
if (content) {
replace(this.el, content);
} else {
remove(this.el);
}
//
}, fallback: function fallback() {
this.compile(extractContent(this.el, true), this.vm);
//把元素的内容抽出来,然后编译
}, unbind: function unbind() {
if (this.unlink) {
this.unlink();
}
//
}
};

先来看bind方法。这里的this指的是<slot>指令,通过name获取到分发的内容,比如 <p slot="one">One</p> 。有分发的内容,那么就添加到slot指令挂载的元素。没有就把slot指令所在元素删除掉。

3.混合

使用混合对象(把选项分离出来,然后组合进组件的选项中)。好处是方便分布复用功能。

第一,简单的混合例子:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<vivi-component></vivi-component>
</div>
<script src="js/vue.js"></script>
<script>
var myMixin={
created:function(){
this.hello();
},
methods:{
hello:function(){
console.log("hello from mixin!");
}
}
};
//myMixin要放在使用之前定义哦。顺序问题很重要。
new Vue({
el:"#app",
components:{
"vivi-component":{
template:"<h1>hello ,vivian!</h1>",
mixins:[myMixin]
}
}
}) </script>
</body>.
</html>

第二,当混合对象与组件有同名选项时,以适当的策略合并。同名钩子函数被并入一个数组中,因而都会被调用。而且顺序是,混合的钩子函数比组件的钩子函数更早被调用。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>混合对象</title>
</head>
<body>
<div id="app">
<vivi-component></vivi-component>
</div>
<script src="js/vue.js"></script>
<script>
var myMixin={
created:function(){
this.hello();
},
methods:{
hello:function(){
console.log("hello from mixin!");
}
}
};
new Vue({
el:"#app",
components:{
"vivi-component":{
template:"<h1>hello ,vivian!</h1>", created:function(){
console.log("组件内容被调用");
},
mixins:[myMixin]
}
}
}) </script>
</body>.
</html>

显示两个钩子函数都有被调用哦.

第三,methods、components、directives都是对象选项,合并时如果键冲突,那么组件的选项优先。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"> </div>
<script src="js/vue.js"></script>
<script>
var myMixin={
methods:{
foo:function(){
console.log("foo");
},
conflicting:function(){
console.log("from mixin");
}
} };
var component=Vue.extend({
mixins:[myMixin],
template:"<h1>hello,vivi</h1>",
methods:{
bar:function(){
console.log("bar");
},
conflicting:function(){
console.log("来自组件本身");
}
}
});
var vm=new component();
vm.foo();//因为混合才有foo方法,所以打印foo
vm.bar();//因为只有组件才有bar方法,所以打印bar
vm.conflicting();//因为这个方法混合对象和组件都有,根据组件优先的原则,所以打印“来自组件本身”。 </script>
</body>.
</html>

调用的打印结果如下

第四,混合全局注册要慎用。会影响之后创建的所有vue实例。大多数情况下,只用于自定义选项。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"> </div>
<script src="js/vue.js"></script>
<script>
Vue.mixin({
created:function(){
var myOption=this.$options.myOption;
if(myOption){
console.log(myOption);
}
}
}
);
var component=Vue.extend({
template:"<h1>hello,vivi!</h1>"
});
new Vue({
el:"#app",
components:{
"my-component":component
},
myOption:"hello"
})
</script>
</body>
</html>

4.动态组件

多个组件可以使用同一个挂载点,然后动态的在它们之间切换。

第一,动态组件的简单例子

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="radio" id="one" value="dev" v-model="currentView"/>
<label for="one">开发</label>
<br/>
<input type="radio" id="two" value="painting" v-model="currentView"/>
<label for="two">画画</label>
<br/>
<input type="radio" id="three" value="travel" v-model="currentView"/>
<label for="three">旅游</label>
<br/>
<template id="dev">
<div>开发</div>
</template>
<template id="painting">
<div>画画</div>
</template>
<template id="travel">
<div>旅游</div>
</template>
<component :is="currentView">
<!--组件在vm.currentView变化时改变-->
</component>
</div>
<script src="js/vue.js"></script>
<script>
var dev=Vue.extend({
template:"#dev",
replace:"true"
});
var painting=Vue.extend({
template:"#painting",
replace:"true"
});
var travel=Vue.extend({
template:"#travel",
replace:true
});
var vm=new Vue({
el:"#app",
data:{
currentView:"dev"
},
components:{
dev:dev,
painting:painting,
travel:travel
}
})
</script>
</body>
</html>

显示效果

第二,

keep-alive特性会让组件重复创建时通过缓存来获取,从而快速创建,当然是提高了视图的性能。

使用的语法如下:

<component :is="currentView" keep-alive>
<!--组件在vm.currentView变化时改变-->
</component>

从源码中可以窥得一二:

第三,activate钩子函数。

它是组件切入前执行。可用来控制组件切换的时长。activate钩子只作用于动态组件切换或者静态组件初始化渲染的过程。不用于使用实例方法手动插入的过程。

完整的代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="radio" id="one" value="dev" v-model="currentView"/>
<label for="one">开发</label>
<br/>
<input type="radio" id="two" value="painting" v-model="currentView"/>
<label for="two">画画</label>
<br/>
<input type="radio" id="three" value="travel" v-model="currentView"/>
<label for="three">旅游</label>
<br/>
<template id="dev">
<div>开发</div>
</template>
<template id="painting">
<div>画画</div>
</template>
<template id="travel">
<div>旅游</div>
</template>
<component :is="currentView" transition="fade" transition-mode="out-in">
<!--改变的代码,先淡出再淡入-->
</component>
</div>
<style>
.fade-transition{
transition:opacity .3s ease;
}
.fade-enter,.fade-leave{
opacity:0;
}
</style>
<script src="js/vue.js"></script>
<script>
var dev=Vue.extend({
template:"#dev",
replace:"true",
activate:function(done){
var self=this;
console.log("在组件替换前打印"); setTimeout(function(){
console.log("计时器中的代码");
done();
},5000);
//延时5秒
}
});
var painting=Vue.extend({
template:"#painting",
replace:"true"
});
var travel=Vue.extend({
template:"#travel",
replace:true
});
var vm=new Vue({
el:"#app",
data:{
currentView:"dev"
},
components:{
dev:dev,
painting:painting,
travel:travel
}
})
</script>
</body>
</html>

可以看到在组件被插入前,它会执行activate函数,做了延时5秒的操作。

第四,transition-mode特性。用于指定两个动态组件之间如何过渡。

代码如下:

 <component :is="currentView" transition="fade" transition-mode="out-in">
<!--改变的代码,先淡出再淡入-->
</component>
<style>
.fade-transition{
transition:opacity .3s ease;
}
.fade-enter,.fade-leave{
opacity:0;
}
</style>

完整的有渐进效果的DEMO:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="radio" id="one" value="dev" v-model="currentView"/>
<label for="one">开发</label>
<br/>
<input type="radio" id="two" value="painting" v-model="currentView"/>
<label for="two">画画</label>
<br/>
<input type="radio" id="three" value="travel" v-model="currentView"/>
<label for="three">旅游</label>
<br/>
<template id="dev">
<div>开发</div>
</template>
<template id="painting">
<div>画画</div>
</template>
<template id="travel">
<div>旅游</div>
</template>
<component :is="currentView" transition="fade" transition-mode="out-in">
<!--改变的代码,先淡出再淡入-->
</component>
</div>
<style>
.fade-transition{
transition:opacity .3s ease;
}
.fade-enter,.fade-leave{
opacity:0;
}
</style>
<script src="js/vue.js"></script>
<script>
var dev=Vue.extend({
template:"#dev",
replace:"true"
});
var painting=Vue.extend({
template:"#painting",
replace:"true"
});
var travel=Vue.extend({
template:"#travel",
replace:true
});
var vm=new Vue({
el:"#app",
data:{
currentView:"dev"
},
components:{
dev:dev,
painting:painting,
travel:travel
}
})
</script>
</body>
</html>

5.生命周期

在vue.js中,实例化vue之前,它们以HTML的文本形式保存在文本编辑器中。当实例化后将经历,创建、编译、销毁3个主要阶段。

生命周期钩子:

(1)init:

在实例开始初始化时同步调用,此时数据观测、事件和watcher都尚未初始化。

(2)created:

在实例创建之后同步调用,此时实例已经结束解析选项,也就是数据绑定、计算属性、方法、watcher/事件回调已经建立。但是还没有开始DOM编译,$el还不存在。

(3)beforeCompile:

在编译开始前调用。

(4)compiled:

编译结束后调用,此时所有的指令已生效,因而数据的变化将触发DOM更新。但是不担保$el已插入文档。

(5)ready:

在编译结束和$el第一次插入文档之后调用,注意必须有vue插入(比如vm.$appendTo())才能触发ready钩子的。

(6)attached:

vm.$el插入DOM时调用。必须是由指令或者实例方法(比如$appendTo())插入,直接操作$vm.el不会触发钩子。

(7)detached

在vm.$el从DOM中删除时调用。必须是由指令或者实例方法删除,直接操作vm.$el不会触发这个钩子。

(8)beforeDestory:

在开始销毁实例时调用,此时实例仍然有功能。

(9)destroyed:

在实例销毁之后调用。

6.开发组件

使用.vue文件实现组件化。具体的代码执行请参看vue.js工具篇的webpack。

<template>
<div class="header">
<h1> {{ title }} </h1>
</div>
</template> <script>
export default {
data: function () {
return {
title: '我是頭部'
}
}
}
</script> <style>
.header {
color: red;
}
</style>

vue.js基础知识篇(6):组件详解的更多相关文章

  1. vue.js基础知识篇(2):指令详解

    第三章:指令 1.语法 指令以v-打头,它的值限定为绑定表达式,它负责的是按照表达式的值应用某些行为到DOM上. 内部指令有v-show,v-else,v-model,v-repeat,v-for,v ...

  2. vue.js基础知识篇(7):表单校验详解

    目录 网盘 第12章:表单校验 1.npm安装vue-validator $ npm install vue-validator 代码示例: var Vue=require("vue&quo ...

  3. vue.js基础知识篇(5):过渡、Method和Vue实例方法

    第8章:过渡 1.CSS过渡 2.JavaScript过渡 3.渐进过渡 第9章:method Vue.js的事件一般通过v-on指令配置在HTML中,虽然也可以在js的代码中使用原生的addEven ...

  4. vue.js基础知识篇(4):过滤器、class与style的绑定2

    代码下载:网盘 欢迎私信 第一章:过滤器 过滤器是对数据进行处理并返回结果的函数. 1.语法 语法是使用管道符"|"进行连接.过滤器可以接收参数,跟在过滤器后面,带引号的参数被当做 ...

  5. vue.js基础知识篇(3):计算属性、表单控件绑定

    第四章:计算属性 为了避免过多的逻辑造成模板的臃肿不堪,可使用计算属性来简化逻辑. 1.什么是计算属性 <!DOCTYPE html><html lang="en" ...

  6. vue.js基础知识篇(1):简介、数据绑定

    目录第一章:vue.js是什么? 第二章:数据绑定第三章:指令第四章:计算属性第五章:表单控件绑定代码链接: http://pan.baidu.com/s/1qXCfzRI 密码: 5j79 第一章: ...

  7. 简单易懂的 Vue.js 基础知识 !

    根 vue 实例 let viewModel = new Vue({ // 包含数据.模板.挂载元素.方法.生命周期钩子等选项 }) Hello Wrold  <!-- 这是我们的 View - ...

  8. Vue.js 基础知识

    0. Vue.js 是轻量级的MVVM框架: 1. index.html:<app></app>:组件载入:入口文件会默认调用一个 main.js: 2. App.vue:入口 ...

  9. Vue.js基础知识

    <!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml&q ...

随机推荐

  1. sqlserver提高篇续集

    七.数据完整性 1.概念:数据一致性和准确性. 分类:域完整性.实体完整性.引用完整性. 解析:域完整性也叫列完整性是指一个数据集对某个列是否有效和确定是否允许为空值.实体完整性也叫行完整性 要求所有 ...

  2. zTree新增的根结点再新增子节点reAsyncChildNodes不生效解决方案

    zTree新增的根结点再新增子节点reAsyncChildNodes不生效解决方案, zTree新的根结点不能异步刷新,reAsyncChildNodes不生效解决方案, reAsyncChildNo ...

  3. Fiddler基础使用一之捕获https请求

    fiddler抓包工具: http协议cookieFiddler是一个调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有的"进出"Fiddle ...

  4. Uva 548 二叉树的递归遍历lrj 白书p155

    直接上代码... (另外也可以在递归的时候统计最优解,不过程序稍微复杂一点) #include <iostream> #include <string> #include &l ...

  5. 斗地主[NOIP2015]

    题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关系根据牌的数码表示如下:3<4< ...

  6. attr(),addClass()使用方法练习

    这次我主要是想要完成2个li之间样式的变化.方法比较傻,如果有人有更好的办法或者有别问题,希望可以不吝指教. <!DOCTYPE html><html> <head> ...

  7. 如何使用Androidstudio创建一个新项目

    首先打开AS,然后 选择第一个选项Start a new Android Studio project 填写包名和项目名,点击next 选择项目类型,点击next 选择UI类型(都是死丢丢帮你生成的) ...

  8. nstallation error: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED报这个错的原因???

    [2015-06-05 20:37:51 - 05ListView列表控件] ------------------------------ [2015-06-05 20:37:51 - 05ListV ...

  9. C语言中全局变量存放在哪个位置?

    今年软考的时候,遇到了这个题目,表示不解,然后考完之后去查了一下百度,才发现自己选错.全局变量存放在静态存储区,位置是固定的. 局部变量在栈空间,栈地址是不固定的.栈:就是那些由编译器在需要的时候分配 ...

  10. FastJson将json解析成含有泛型对象,内部泛型对象再次解析出错的解决办法(Android)

    折腾小半天的问题,这里先感谢一下深圳的小伙子,远程帮我搞,虽然也没有搞出来==========FUCK 声明:Android开发下发生此异常,Java开发下并不会有这个问题 异常重现 简单说一下抛出异 ...