- 两个vue实例
var vm1 new Vue({
)}
var vm2 new Vue({
)}
- 外部js访问vm:
vm1.title = "ok"
实际上vm1内部用this访问其自身,外部用vm1来访问它
-
也可以在vm2里面
vm1.title = "ok" -
data可以在外面js创建
var data = {
title="ok"
number=1
}
var vm1 new Vue({
el:app1,
data = data,
)}
-
vm的属性可以在外部添加,但没用,缺少vue的响应式特点:
vm1.newProp = 'New!' ,可以这样设置,但没有了响应式 -
vm中自动创建了很多get,set之类的属性,很多,这些东西构成了vue框架,
用console.log(vm1),然后按按F12可以观察。
比如说:
console.log(vm1.$data.title) // 这个$就是系统默认的一个东西 -
ref
ref是可以添加在任何html元素上:ref= "xxx"即可
在vue中用:this.$refs列出全部$refs元素,this.$refs.xxx 访问指定的单个元素
要点:通过$refs改变DOM元素的内容,并非在vue框架下的行为,当vue重新渲染时它还是会根据模板来设置数据,你的修改无效
$refs是取代queryselctor的好方法,但是用它来修改元素值不好 -
$mount (小知识:$前缀的属性,多半是Vue原生共给的方法或属性)
var vm1 new Vue({
el:'app1'
)}
以上说明将vm1挂到一个id=app1的div上
var vm1 new Vue({
)}
去掉el, 还可以这样:
vm1.$mount('app1')
这就是$mount的作用:挂载,
作用和设置el一样。$mount的好处是我们可以先创建vue,事后再挂载到DOM的某处。
template的用法:
var vm1=new Vue({
template: '<h1>Hello world</h1>' //直接在创建vue实例的时候设置模板
)}
然后,甚至也可以使用原生JS命令来挂载:
document.getElementById('app1').appendChild(vm1.$el)来设置其中的el属性来挂载,但是这比较罕见。
-
vue 虚拟dom 真实dom的关系
在vue和dom之间,还有一层虚拟dom, 虚拟dom是真实dom的一份拷贝,
vue 随时观察这虚拟dom,因为没有渲染动作,他们的交互速度是极快的,
当虚拟dom的值和dom确实发生改变的时候,才去改变真实dom的元素。
比如说vue有一名为message的变量,值是hello world,现在我们把他修改为Hello everyone,
首先,vue会将它快速反映到虚拟dom上,然后,再对比真实dom,发其中一个元素变了,
它就只会去渲染这其中一个元素,避免了全局dom变动。 -
vue的生命周期
-
beforeCreate() -> 初始化Data和Events
-
created() -> 编译模板(template)或者el的template (比如说是直接从HTML中读取,还是从template属性中读取)
-
beforeMount() ->尚未将模板挂载到DOM的时候发生-> 将模板转换成真正的HTML代码
-
mounted() -> 写入DOM
以上一个Vue就被创建好了,在运行时,当数据发生变化的时候,也会触发两个钩子:
当数据发生变化而且需要重新渲染的DOM的时候被调用:beforeUpdate(),在数据渲染完毕后调用updated()
注意这两个钩子不属于Vue的“生命周期”范畴,而是当Vue在存续时间内,当某个数据发生变化时触发的东西。 -
beforeDestory() -> 当决定要销毁Vue实例但又还没有真正销毁时触发。
-
destroyed() -> Vue实例已经被销毁时触发。
要点:
beforeUpdate() 和 updated() 必须是值真正发生变化才会触发,比如你反复修改message变量,但值一直是'Hello',则
不会反复触发这两个钩子,这就是前面所讲的虚拟DOM在起作用,数据没有真正变化,不做渲染动作。
beforeDestory() 和destroyed() 必须显式地用:this.$destroy() 才会触发。
- component (组件)
要点:
一个component就是一个vue实例,通过el: 名字命名,然后在全局Vue中注册它:
Vue.component('名字')
然后每一个new Vue,都会自动加载这个component (组件),
定义方法:
a) 直接嵌入式:
Vue.component('hello',{
template: '<h1>Hello world</h1>'
})
相当于自定义了一个HTML标签<hell></hello> ,可以在HTML文档的任意地方使用,就是显示一行字:Hello world
这里有一个重点,我们总是会看到,在根实例创建的时候,data是长这样的:
new Vue({
el: '#app',
data: {
a: '',
b:'',
}
})
但在组件中变成了这样:
data() {
return {
a: '',
b:'',
}
},
这个return将data封装成了一个函数,变量通过这个名为data的函数携带出来了,
理论插入:
在vue中,所有同名组件共享同样的data对象,比如你的页面中嵌入了3个自定义组件<hello>,
其实这三个<hello>是共享同一个data的, 当你修改某一个实例的data对象的一个属性的时候,
公用的data对象也会发生改变,即3个<hello>的data同时改变,这明显不是我们想要的效果。
将组件的data封装成一个函数,这样做的目的是,data不再是一个对象名,
而是一个函数,可以创建属一块私有空间,让各个组件维护各自的数据。
-
关于this :
this只会只想这个Vue组件实例的对象,并不会产生像data那样共享数据的问题。 -
全局组件与局部组件
-- 全局组件使用Vue.component('组件名', 对象名) 注册,组件实例既可以是直接内嵌,也可以import一个
-- 局部组件采用变量的方法注册,
首先定义一个组件,当然此处也可以import
let cmp = {
data: function() {
return {
xx:0,
}
},
template: '',
methods:{
},
}
然后在一个Vue实例中,加入到它的component属性中:
new Vue({
el: "#app",
components: {
cmp
},
template: '',
methods: {
},
})
-- 关于render: h => h(App)
这个其实就是template属性的替代品,
-- 关于export default
这个其实是JS的知识,而不是Vue的内容了,
在JS中import 函数 from 文件,
理论上import的函数名,必须在文件中以 export 显式的提供,比如code.js文件中有:
function aaa(){
console.log('Hi')
}
export {aaa}
你在import的时候只能这样:
import {aaa} from code.js
使用的时候直接使用函数名aaa() 调用。
但是,当文件中有export default的时候,import的时候可以用任意名称来取代它,
比如还是code.js,代码如下:
export default {
aaa:function() {
console.log('hi')
}
}
import的时候:
import Heeellooo from code.js
导出的函数名随你高兴,可以自定义。
使用:Heeellooo.aaa() 来调用
要点整理:
- 注册组件:
全局法:Vue.component('组件名', 对象名)
局部法:在实例的component属性中添加组件代码
组件的本质:你可以把它想象成一个自定义的HTML标签
组件对象代码怎么来:
a. 内嵌:
Vue.component('aaa', {template:'<h1>Hello</h1>'})
b. 变量:
let aaa = {
template:'<h1>Hello</h1>'
}
Vue.component('aaa', aaa)
c. import :
import aaa from code.js
Vue.component('aaa', aaa)
- 知识点:
new Vue({
el: "#app",
store,
router,
components: {
App,
Post,
},
这里面store和router运用了ES6新语法,
store和router是vue的两个属性,当属性名和对象名是一样的时候,可以省略写成一个,说白了就是:
store:store
router:router
这种格式的简写。
-- 组件之间的通讯
-
父组件 -> 子组件 [props]
父组件data中有一个变量:name
在子组件需要用props属性引用:
export default {
props:['name'] //数组中嵌入变量名
}
在引用子组件的HTML标签中加入,例如hello标签:<hello :name="name">
要点:要引用父组件变量name,子组件props中要添加name,模板中用{{name}},引用标签要增加:name = "name"
当然,以上四处地方也并非只能使用name这个变量名,例如在子组件中用myName代替:
父组件还是name变量,
子组件props中可写为: props:['myName']
模板中写为: {{myName}}
标签中写为: :myName = "name"
效果一样。
除了模板之外,在子组件任何地方都可以用this来访问这个变量,例如在methods中:
methods: {
aaa:function() {
console.log(this.myName)
}
}, -
props的验证:
export default {
props: {
myName: {
type: String, //必须是String类型
defalut: 'Hello'
}
}
myName必须是String,默认值是Hello
-- 反向传值: 子组件到父组件:
第1步: 在子组件中$emit()通知父组件 ,例如:
当完成某个操作后,通知父组件并传值,有点类似回调函数
this.$emit('ok', this.myName) // 设置一个通知函数ok, 传回变量myName
第2步:在引用子组件的标签中标明这个函数,例如:
<hello :name="name" @ok='代码'>
这里的"代码",既可以是一个函数,也可以直接就是一个变量名,也可以是一行代码。
---------扩展阅读---------------在使用elment-ui的diaglog对话窗中,如果子组件是对话窗,在关闭的时候将false传回给父组件,
vue报错:void mutating a prop directly since the value will be overwritten whenever the parent component re-renders.
Instead, use a data or computed property based on the prop's value. Prop being mutated:
按上面的“正规”操作,会报这个警告,尽管不影响使用,但很烦人,解决方案:
http://www.manongjc.com/detail/11-tfljzfuejzpgadt.html
父组件中设置要点:
-
data() {
return {
profileShow: false, //弹窗总开关
}; -
标签: <profile :isShow="profileShow" @profileClose="profileShow=$event"></profile>
子组件中设置要点:
-
标签:
<el-dialog
:visible.sync="currentIsShow"
@close="handleClose()"> -
data() {
return {
currentIsShow: this.isShow,
} -
props: ['isShow'],
-
关窗事件:
methods: {
handleClose: function () {
this.$emit('profileClose', this.currentIsShow);
},
网友评论