vue实例(对象)
const vm = new Vue(options)根据options里的内容返回一个vue实例(对象)命名为vm- 把Vue的实例命名为vm是尤雨溪的习惯,我们应该沿用
- 这个vm对象封装了对视图的所有操作,包括数据读写、事件绑定、DOM更新(注意,无Ajax)
- vm的构造函数是Vue,按照ES6的说法,vm所属的类是Vue
- options(一个对象)是new Vue的参数,一般称之为选项或构造选项(构造函数后面的选项)

组件
-
组件被vue实例使用
-
组件可以由一个vue文件生成,也可以我们声明一个组件(内容和options一模一样,除了data必须用函数)
-
组件名开头大写
options的五类属性
数据
data内部数据props外部数据,也叫属性propsData用不着学computed倍计算出来的methods面向对象的函数,也就是使用时要obj.sayHi()(普通函数sayHi())watch
DOM
el挂载点template在完整版里的视图render在非完整版里的视图,用不着学renderError在非完整版里的视图失败了
生命周期钩子:
beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedactivateddeactivatedbeforeDestroydestroyederrorCaptured先不看,用到再查文档
资源
directives指令filters过滤器(不要用了),用methods代替components组件,如Demo.vue
组合
parent先不看,用到再查文档mixins混入extends扩展provideinject注入
其他
先不看,用到再查文档
el--挂载点
你的组件、你的实例的挂载点。
- 两个用法
new Vue({
el: "#app"
});
new Vue({}).$mount('#app')
- 被你选为挂载点的那个元素,如果在index.html里那个元素里面本来就有内容,在渲染时会消失,被这个vue实例的对应内容所覆盖。除非你网速慢,js还没加载好。
data -- 内部数据
- 两个用法:对象和函数(函数里返回对象就行了),优先使用函数
new Vue({
data() {
return {
n: 0,
array:[1,2,3]
}
}
}).$mount("#app");
- 有bug,在数据响应式时在了解
methods -方法
- 两个用法
- 事件处理函数
- 普通函数(直接在视图里调用,每一次更新渲染都会调用一次)
import Vue from "vue";
Vue.config.productionTip = false;
new Vue({
data() {
return {
n: 0,
array: [1, 2, 3, 4, 5, 6, 7, 8]
};
},
template: `
<div class=red>
{{n}}
<button @click="add">+1</button> //事件处理函数
<hr>
{{filter()}} //普通函数(直接在视图里调用,每一次更新渲染都会调用一次)
</div>
`,
methods: {
add() {
this.n += 1; //事件处理函数
},
filter() {
return this.array.filter(i => i % 2 === 0); //普通函数
}
}
}).$mount("#app");
components--Vue组件
注意大小写 三种引入方式,推荐最后一种
方法一:推荐使用,很模块化
- 新建一个vue文件Demo.vue,这个vue文件就是一个组件
- 在main.js中引入这个vue文件
- 在vue实例的components中声明这是我要用的组件,并且命名为Demo1
- 这样在这个Vue实例的template中就可以直接使用这个组件
<Demo1/>
import Vue from "vue";
import Demo from "./Demo.vue"; //引入这个vue文件
Vue.config.productionTip = false;
new Vue({
components: {
Demo1: Demo //在vue实例的components中声明这是我要用的组件,并且命名为Demo1
//如果组件名就叫Demo,即Demo:Demo,那就写Demo
//components: {Demo},
},
data() {
return {
n: 0
};
},
template: `
<div class=red>
{{n}}
<button @click="add">+1</button>
<Demo1/> //这样在这个Vue实例的template中就可以直接使用这个组件`<Demo1/>`
</div>
`,
methods: {
add() {
this.n += 1;
},
}
}).$mount("#app");
方法二:全局
- 在main.js里直接写一个全局组件,写组件名字和内容(内容和options一模一样,除了data必须用函数)
- 直接在任何Vue实例的template中就可以使用这个组件
<Demo2/>
import Vue from "vue";
Vue.config.productionTip = false;
Vue.components('Demo2,{template:`<div>Demo2</div>`}') //在main.js里直接写一个全局组件,写组件名字和内容
new Vue({
data() {
return {
n: 0
};
},
template: `
<div class=red>
{{n}}
<button @click="add">+1</button>
<Demo2/> //直接在任何Vue实例的template中就可以使用这个组件`<Demo2/>`
</div>
`,
methods: {
add() {
this.n += 1;
}
}
}).$mount("#app");
方法三:上面结合
在vue实例的components中写这个vue实例要用的组件,组件名为Demo3,内容为和options一模一样,除了data必须用函数
import Vue from "vue";
Vue.config.productionTip = false;
new Vue({
components: {
Demo3: { template: `<div>Demo2</div>` } //在vue实例的components中写这个vue实例要用的组件,组件名为Demo3,内容和options一模一样,除了data必须用函数
},
data() {
return {
n: 0
};
},
template: `
<div class=red>
{{n}}
<button @click="add">+1</button>
<Demo3/> //直接在这个Vue实例的template中就可以使用这个组件`<Demo3/>`
</div>
`,
methods: {
add() {
this.n += 1;
}
}
}).$mount("#app");
四个钩子
- created -- 实例出现在内存中后触发
- mounted-- 实例出现在页面中(挂载了)后触发
- updated -- 实例更新了后触发
- destroyed -- 实例从页面和内存中消亡了后触发
props-外部数据、属性
message="n"传入字符串:message="n"传入vue实例的this.n数据:fn="add"传入vue实例的this.add函数
我是一个组件,我的props指 属性名是我定义在我自己里面,我的template也用到了这些属性,但是属性值是从外面传给我的
(所以我自己不能改这个属性值的,属性值是从外面来的,所以我自己就算改了,外面的改了之后我的属性值还是得跟着外面的来。我就是想要修改!请看最下面)
外面咋传给我?外面的Vue实例在引用我这个组件的时候传给我。
在Demo.vue组件里
<template>
<div class="red">
这是Demo内部
{{message}} //我要用message
<button @click="fn">点我</button> //我要用fn
</div>
</template>
<script>
export default {
props: ["message", "fn"]
//表示本组件可以接受一个参数message和fn,但是message和fn的值不是从我这里传入的,是外面传给我的。
//所以message和fn就是Demo的外部数据(属性名是我定义在我自己里面,我的template也用到了这些属性,但是属性值是从外面传给我的)
};
</script>
<style scoped>
.red{
color: :red;
}
</style>
在main.js里
import Vue from "vue";
import Demo from "./Demo.vue";
Vue.config.productionTip = false;
new Vue({
components: { Demo },
data() {
return { n: 0 };
},
template: `
<div>
<Demo message="n"/> //在引用Demo组件时把他要用的message的值传入,值就为一个字符串n
<Demo :message="n"/> //在引用Demo组件时把他要用的message的值传入,值为这个Vue实例的data里的n
<Demo :fn="f1"/> //在引用Demo组件时把他要用的fn的值传入,值为这个Vue实例的methods里的f1
</div>
`,
methods: {
f1() {
console.log("Hi");
}
}
}).$mount("#app");
例子(非完整版Vue)
-
组件不可以修改props!!!外部给组件的,你怎么说修改就修改?
-
我(组件)就是想要改我的一个props:money,也就是外部(父组件)给我total
-
可以!你通知外部你想咋改,外部来改,你不也就同时被改了吗
-
怎么通知?eventBus!但在Vue里面是
-
儿子用
$emit触发updata-xxx事件,同时还得传参数,参数是儿子想怎么对自己的外部数据的操作);<button @click="$emit('update:money', money-100)"> -
爸爸在引用儿子的时候用
v-on监听updata-xxx事件,他的事件处理函数会自动有那个参数,为可以用$event获得那个参数,因为爸爸是把自己的total赋值给儿子的外部数据的。所以事件处理函数就为把参数给自己的total。(儿子想怎么操作自己的外部数据,爸爸本来是把自己的total给儿子的外部数据的。那么爸爸(通过监听updata:money事件和$event)知道儿子想怎么操作他自己的外部数据,爸爸就让自己的total等于儿子的操作就行了。)<Child :money="total" v-on:updata:money="total= $event"/>注意,完全等同于
<Child :money.sync="total"/>(同步)(语法糖)
-
儿子想咋改,写在
$emit的第二个参数里;爸爸就会从v-on里用$event获取$emit的那个参数就知道儿子是想咋改的,爸爸就会把这个结果给自己的total。 -
爸爸的total改了,儿子的money不就给改了??!!成功
写一个(子)组件Child.vue
<template>
<div class="child">
{{money}} //儿子这里要显示钱
<button @click="$emit('update:money', money-100)">
//儿子每次点击按钮就是想花钱,可是钱是爸爸给的自己花不了。
//那就每次花钱的时候触发花钱事件update:money,这个事件会把爸爸给的钱-100,也就是儿子想怎么把这个钱花掉
<span>花钱</span>
</button>
</div>
</template>
<script>
export default {
props: ["money"] //儿子需要父亲给钱money
};
</script>
<style>
.child {
border: 3px solid green;
}
</style>
写一个(父)组件App.vue ,这就是非完整版要用的vue文件
<template>
<div class="app">
App.vue 我现在有 {{total}}
<hr>
<Child :money="total" v-on:updata:money="total= $event"/>
//爸爸在引用儿子的时候,先把自己的钱total给儿子money,在监听儿子的花钱事件updata:money,只要儿子花钱了,就把自己现在的钱total的金额=儿子想怎么花掉这钱$event。爸爸的total变了,儿子的money也变了
//爸爸把total给儿子当他的money,要是儿子想改money就通知爸爸改爸爸的total
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
data() {
return { total: 10000 };
},
components: { Child: Child }
};
</script>
<style>
.app {
border: 3px solid red;
padding: 10px;
}
</style>
总结:vue的修饰符sync的功能是:当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定的。sync是个语法糖。他是尤雨溪为我们写的<Child :money="total" v-on:updata:money="total= $event"/>的简写形式。
- 子组件的外部数据是xxx ,父组件把自己的yyy给子组件当xxx的值。子组件想修改自己的外部数据xxx,只需要在某个时刻
this.$emit('updata:xxx',想咋改),父组件:xxx.sync='yyy'就行了(父组件首先把自己的yyy给子组件当xxx,之后如果想改父组件会把自己的yyy改了)
通信
目的:父组件想要子组件的信息
做法
- 首先,父组件在使用子组件时要监听一个事件,事件处理函数中会自动有个参数就是父组件想要的信息,这样我们就可以对信息进行操作
<template>
<Tags @updata:tags="onUpdateTags"/>
</template>
<script>
onUpdateTags(selectedTags: string[]) {
console.log(selectedTags);
}
<script/>
- 其次,子组件需要在某个时刻触发这个事件,同时必须把父组件想要的自己的信息当第二个参数。
this.$emit("updata:tags",this.selectedTags)
- 那么,子组件触发这个事件,父组件监听到了,信息也传过来了,父组件里的事件处理函数开始执行了----父组件就可以对信息操作了
例子---子组件想要修改自己的props
描述
- 子组件想要修改自己的props:money的值,不能,因为props:money的值是父组件把自己的total传给子组件的。
- 所以可以用通信。让父组件知道子组件想怎么样修改props:money的值,父组件改自己的total不就好了
步骤
-
因为子组件是想点击按钮时想让props:money的值减掉100,所以在点击按钮时
$emit触发updata:money事件,同时因为父组件想知道子组件是怎么修改的,所以把这个信息作为第二个参数<button @click="$emit('update:money', money-100)"> -
那么父组件在使用子组件时,监听
updata:money事件,事件处理函数中有个参数$event就是信息,把信息给total就行了 -
<Child :money="total" v-on:updata:money="total= $event"/> -
那么,子组件点击按钮会触发
updata:money事件,父组件监听到了,怎么修改money信息也传过来了,监听函数执行了,就可以把这个信息给total了,那么money的值不也被修改了吗!