文章目录
前言
学习总结
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:
<div id="app">
{{msg}}
</div>
<script>
let app = new Vue({
el: '#app',// el:是元素(elemen)的缩写 指定此实例所管理的模板
data: {
msg: "你好 Vue.js"
}
})
</script>
Vue叫类,也叫构造器,new 类 得到一个对象,app,Vue实例
new Vue时,传递一个对象,这个对象,叫配置对象
。
el 表示此vue实例管理的模板 一个vue实例,对应一个模板。
data中的我们叫数据,也叫状态。
放到data中的状态,都是响应式的。
所谓的响应式,就是指,如果数据变了,界面会自动刷新。
Object.freeze(obj); // 把obj中的数据冻起来,就表示响应式系统不起作用
vue实例中有数据源 data,数据源是给模板提供数据的。
数据源的写法有两种:
- 1)data是一个对象
- 2)data可以是函数,必须返回一个对象,数据放到此对象中
new 一个Vue,得到的实例,叫根实例。根实例的data的写法有两种,不是根实例data的写法,只能写在函数的形式。
app,叫根实例,这个根实例代理了data中的所有的数据
app.xxx app.message app.name 就可以得到data中的数据
1 Vue.js指令
指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
默认情况下,input中输入的内容是不受状态的控制的,叫非受控表单。
事件绑定
v-bind: 表示把data中的数据绑定到属性节点位置;可以简写为:
。(单向绑定)
v-model:如果你输入框中的数据变了,vue层数据也会变。(双向绑定)(通常用于收集表单数据)
v-on:是用来给某个标签绑定一个事件。(简写为:@
)
v-text
:把数据绑定到文本结点上,但不会解析代码。语法糖==>{{}}
更常用,写在元素内。
v-html:和v-text类似,但会解析html代码。
{{}}:可以对数据做简单的运算,只能放表达式(任何有值的内容都是表达式
)。
v-show:根据条件展示元素(切换元素的 CSS property display)。(类似v-if)
v-if:根据后接的表达式真假来插入/移出当前元素。
(下面条件渲染中有详解)
v-else:来表示 v-if 的“else 块”( 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。)
v-else-if:顾名思义,充当 v-if 的“else-if 块”,可以连续使用。(必须紧跟在带 v-if 或者 v-else-if 的元素之后。)
key:来表达“这两个元素是完全独立的,不要复用它们”。(每次切换时,输入框都将被重新渲染。)
<div id="app">
<p v-bind:title='msg'>鼠标提示信息</p>
<input type="text" v-model="msg">
<p>{{ message }}</p>
<!-- v-on: 是用来给某个标签绑定一个事件 -->
<button v-on:click="reverseMessage">反转消息</button>
<p v-text="msg1"></p>
<p v-html="msg2"></p>
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: "你好 Vue.js",
msg1:"<h1>text你好!</h1>",
msg2:"<h1>html你好!</h1>"
message: 'Hello Vue.js!'
},
computed: {// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
// 在配置项,有一个methods配置项
// 这个配置项中就放了很多的方法,是给模板提供的
// 在data中也可以写函数,建议写在methods中
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
},
watch: {// 侦听器
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
})
</script>
在 元素上使用 v-if 条件渲染分组
因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个
<template>
元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含<template>
元素。
计算属性缓存vs方法
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
小胡子{{}}语法
1)小胡子也是数据绑定,只不过是单向数据绑定, 是v-text的语法糖, 基本上我们很少使用v-text指令。
2)在小胡子中,可以对数据进行简单运算, 在小胡子中,只能放表达式(任何有值的内容都是表达式)。
表达式:
1 "hello" var a = 1;
a = 1 是一个表达式 =叫赋值运算符 赋值运算符是有副作用的 整体也有一个 整体的值是右值
var a = 1 不叫表达式 叫语句 因为Var是用来声明一个语句的
function f(){ return 123 } f()叫函数调用 函数调用的结果是一个值
3)在小胡子中也可以放函数调用(因为函数调用也是得到一个值)
4)在小胡子也可以放三目/元运算符(因为三目运算符最终的结果也是一个值)
5)在小胡子中,不能放语句(因为语句没有值)
6)在小胡子中,只能放data中定义好的响应式数据
注意点:
- 小胡子,只能写在文本节点的位置。
- 小胡子,放数据,直接写数据就OK了,不需要写data.xxx。
- 小胡子,只能放data中定义好的响应式数据。
- 在使用小胡子,最好使用标签包起来,如果不包,最终编译出的数据也没有标签包裹,后面操作就不方便,方便获取 。
Style绑定
要绑定style,style后面需要跟一个对象,对象中写样式。
如果你的样式中有-
,把-
去掉,后面单词的首字母大写(中划线命名,换成小驼峰命名
)。
<div id="app">
<p :style="{ fontSize:fs }">{{name}}</p>
<hr>
<!-- style后面可以跟一个数组 -->
<p :style="[baseStyles,overredeStyle]">hello style绑定</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
fs:"40px",
baseStyles:{
width:"100px",
height:"100px",
},
overredeStyle:{
background:"red"
}
}
})
</script>
结果展示:
Class绑定
1) :class="abc" abc是状态
2) :class 后面写三目 控制一个类有还是没有
3) :class 后面写对象 控制多个类有还是没有
4) :class 后面写数组 控制多个类有还是没有
<div id="app">
<div :class="a"></div>
<div :class=" flag ? 'box' : 'box2' "></div>// flag:true/false
<div :class="{box:flag,box3:false}"></div>// true显示;false不显示
<div :class="['box','box3']"></div>// 类似 class="box box3"
</div>
条件渲染
v-if: 后跟状态可以控制一个盒子是否创建,是否销毁。(直接从源码阶段消失
)
v-else: 来表示v-if的“else块”。(v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
)
v-else-if: 充当 v-if 的“else-if 块”,可以连续使用(类似于 v-else,v-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。
)
v-show: 是通过css来控制盒子是否显示和隐藏。(display=none
)
<div v-if="flag" class="box">我是一个盒子</div>
<hr>
<!-- v-show是通过css来控制盒子是否显示和隐藏 -->
<div v-show="flag" class="box">我是一个盒子</div>
<!-- v-if和v-else之间不能有其它内容,有的话,就警告了 -->
<!-- 尽量使用 template标签-->
<template v-if="flag2">
<h1>hello vue</h1>
<p>haha</p>
</template>
<template v-else>
<h1>hi vue</h1>
<p>xixi</p>
</template>
默认情况下,<template>
是隐藏的,实际是默认其display属性为none。
HTML内容模板(<template>
)元素是一种用于保存客户端内容机制,该内容在加载页面时不会呈现,但随后可以在运行时使用JavaScript实例化。
将模板视为一个可存储在文档中以便后续使用的内容片段。
虽然解析器在加载页面时确实会处理<template>元素的内容,
但这样做只是为了确保这些内容有效;但元素内容不会被渲染。
摘自Vue.js官方:
不推荐同时使用 v-if 和 v-for。
当 v-if
与 v-for
一起使用时,v-for
具有比v-if
更高的优先级。
列表渲染
v-for
:指令基于一个数组来渲染一个列表。
v-for:
循环一个数组
循环一个对象
循环一个数字
v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
v-for写在谁上面,最终就渲染出多个谁。
v-for="(item,index) in news" 写法是固定的:(可以用of替换in)
item
是数组中每一项 index
是数组中的索引。
名字可以叫其它的名字。
v-for嵌套
<div id="app">
<ul>
<li v-for="(item,index) in news">
{{ item }} ----------- 索引:{{ index }}
</li>
</ul>
<!--循环一个数字-->
<span v-for="n in 10">{{ n }} </span>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
news:["新闻1","新闻2","新闻3","新闻4","新闻5","新闻6","新闻7"],
}
})
</script>
结果展示:
2 事件绑定v-on
事件处理
v-on:click叫事件绑定 f1此时是一个函数
<button v-on:click="f1">按钮1</button>
<button @click="f1(1,2,3)">按钮2</button>//简写形式
f1写在methods中,在data中也可以写函数,但不建议
如果监听器的写法,没有写(),在监听器中的第1个参数就是事件对象。
如果监听器的写法,写了(), 在监听器中的第1个参数就不是事件对象,就是你传的实参
问题:我要传参,我还要在监听器中获取事件对象
答:手动传递事件对象 $event
<button v-on:click="f3(110, $event)">按钮3</button>
如果监听器的代码比较简单,可以直接把监听器写在模板中。(counter叫状态
)
<h1>{{ counter }}</h1>
<button @click=" counter += 1 ">加1</button>
<button @click=" counter -= 1 ">减1</button>
<!-- data: {counter:0} -->
结果展示:
事件修饰符
修饰符可以串联
.stop: 阻止事件冒泡。相当于e.stopPropagation();
.prevent: 阻止默认行为(提交事件不再重新加载页面、a跳转链接...
)。相当于e.preventDefault();
.once: 事件将只会触发一次 。
.capture:添加事件监听器时使用事件捕获模式。(即内部元素触发的事件先在此处理,然后才交由内部元素进行处理
)
.self:只有event.target是当前操作的元素自身时触发处理函数。
.passive:事件的默认行为为立即执行,无需等待事件回调执行完毕。
<div style="width: 200px; height: 200px; background-color: red;" @click="four">
<!-- stop 叫事件修饰符 -->
<button @click.stop="five">five</button>
</div>
four包裹了five,点击five也会触发four的绑定事件。
3 计算属性和侦听器
created:
- vm 是有生命周期的,在这些生命周期过程中,有些函数会自动调用
- created 就是当vm挂载到DOM树上时,会自动调用,这此函数,叫生命周期函数,也叫钩子函数
computed:
- computed叫计算出来的数据,根据上面的data,计算出一个新的数据,这个新的数据,叫计算属性。
- 所谓的computed,就是说根据已有的数据,计算出一个新的数据。
- 计算属性本质是一个函数,写代码时,需要写成函数,在模板中使用时,需要当成数据来用
- 计算属性是有缓存的 如果计算过一次,后面再使用时,就会重新计算了,只有当data发生了改变,才会重新计算。
- 当数据发生了改变,计算属性会重新计算。
methods:
- 在模板中,只在调用一次方法,就会把方法执行了 。
- 方法每用一次都要调用一次。
注意:一般情况下,能使用计算属性实现的业务,使用方法也能实现,但是尽量使用计算属性。
watch:
- 同一具需求,使用方法,使用计算属性,使用侦听器都可以实现。
- 侦听器 侦听data中的数据 如果数据变了,我们要侦听到它变了
- 侦听器,一般是用来侦听data中某一个数据是否发生了改变了
var app = new Vue({
el: '#app',
created(){
this.userName = this.firstName + this.lastName;
},
data: {
firstName:"Wang",
lastName:"Cai",
person:{
username:"qq",
age:10,
address:"bj"
}
},
computed:{//计算属性是有缓存的 如果计算过一次,后面再使用时,就会重新计算了,只有当data发生了改变,才会重新计算
// 计算属性的写法1:
fullName(){//写的时候是函数 用的时候当成数据来用
return this.firstName + this.lastName
}
},
methods:{//在模板中,只在调用一次方法,就会把方法执行了
getFullName(){
return this.firstName + this.lastName;
}
},
watch:{
// 同一具需求,使用方法,使用计算属性,使用侦听器都可以实现。
// 侦听器 侦听data中的数据 如果数据变了,我们要侦听到它变了
// 侦听器,一般是用来侦听data中某一个数据是否发生了改变了
//表示侦听firstName
// newVal表示新值,oldVal表示上一次的值
firstName(newVal,oldVal){}//新值 旧值
// 侦听器的另一种写法
// app.person = {a:1} 修改person
// app.person.username = "xx" 修改person内部的属性
// 默认情况下,只能侦听你的person数据是否改变,不能侦听person内部的属性是否发生改变了
// 如果想让它深度侦听 deep:true
person:{
handler(newVal){
console.log("person变了");
},
deep:true,
immediate:true, // 一上来就先走handler,之前是只有数据变了,才走handler
}
}
})
4 Vue实例
模板的分类
// 根实例
var app = new Vue({
// el: '#app', // 指定此实例所管理的模板
// 指定内部模板
// template:"<div>内部模板</div>",
// el指定外部模板 template是指定内部模板 使用render函数渲染模板
// 模板都需要编译 最终都要编译成render函数 render函数生成虚拟DOM
// 虚拟DOM(JS对象)转换成真实ODM,替换掉页面上的<div id="app"></div>
render(h){
// h 是用来创建虚拟DOM的 {}这里是属性节点 []文本节点
return h("div",{},["hello render 函数"])
},
data: {
name:"wangcai"
},
methods:{
f1(){
console.log("f1.....");
}
}
})
// 如果使用template指定内部模板,需要手动挂载到真实DOM上
// 把模板编译换,替换到上面的#app
app.$mount("#app");
vue根实例的生命周期
研究vue的生命周期,实际上说的是vue实例的生命周期,主要是指生命周期中的一些函数,
这个函数,会在合适的时机,自动调用,不需要我们去调用,这个函数,叫生命周期函数,
也叫钩子函数,如下:
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
beforeCreate: Create表示创建,创建vm实例
基本上没有什么用,在vm实例创建之前,此函数中,不能获取vm实例 this
是没有办法得到DOM元素的,因为DOM元素还没挂载到页面上
created
vm实例已创建完毕,vm可以工作了,在引钩子中,就可以获取data中的数据,调用methods中的方法了。
但是还不能获取DOM元素,因为DOM元素,还没有挂载到页面上。
在此勾子函数中,就可以发送ajax请求,在vue中发送ajax请求,一般会使用axios。 但是vue中基本上不会使用jq,或jq中的ajax
beforeMount 了解
vm也已经工作了,可以获取数据,可以调用方法
表示DOM元素挂载到页面之前调用,也没有什么用,因为DOM也获取不了。
基本上也没有人在这个钩子中发送ajax请求。
mounted
DOM元素已经挂载OK了,我们已经看到网页了。此钩子中:
1)获取data中的数据
2)调用methods中的方法
3)也可以发送ajax请求 有些人就喜欢在mounted这个钩子中发送ajax请求
4)获取渲染好的DOM元素
beforeUpdate UPdate就是模板
当状态改变时,会自动刷新的模板,此时就会调用beforeUpdate。在这个钩子函数中,
获取的数据是最新的数据,但是页面上的数据还是老数据。
updated
页面已经渲染完毕,页面上的数据就变成了最新的数据。
问:你能不能在updated中改变数据?
答:不能 如果修改了,可能会造成死循环
beforeDestroy 有用
在vm实例死之前,会调用beforeDestroy,在这个钩子,可以做一些收尾工作(后面说)
destroyed 没用
vm已死,此钩子没什么用
现在我们需要掌握的:
1)created 可以发送ajax请求 获取数据 调用方法
2)mounted 可以发送ajax请求 可以获取DOM元素 获取数据 调用方法
3)beforeDestroy vm在死亡之前调用 收尾工作
5 组件间通信
个人理解:无论是子传父还是父传子,传递的数据都只是数据(只能是值),你要什么我传给你什么,不指定内容无法接收到数据。
详解:传送门
6 组件注册和
组件命名方面尽量使用短横线分隔命名(keybab-case),使用PascalCase(首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说<my-component-name>
和 <MyComponentName>
都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
组件名注册时,使用小驼峰,在模板中使用时,需要转成中划线。
全局注册
使用Vue.component
的组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。
Vue.component("组件名",{
template:`<h1>写模板内容</h1>`,
methods: {
fn(){console.log("写函数方法");}
},
// 等等...
})
局部注册
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
<div id="app">
<!-- 3)使用组件 使用组件是使用的是注册名 -->
<my-com></my-com>
</div>
<!-- 定义组件的模板 -->
<template id="box">
<div>
<h1>我是一个小组件</h1>
</div>
</template>
<script>
// 1) 定义组件对象
let com = { // 这里尽量不要写成短横线分隔命名
template:"#box"
}
var app = new Vue({
el: '#app',
data: {
name:"wangcai"
},
methods:{
f1(){
console.log("f1.....");
}
},
// 2)把某个组件注册进来 局部注册 只能在这个#app模板中使用
components:{
//com 直接拿变量名作为注册名
//或者参数1表示注册名 参数2表示组件对象
"my-com":com
}
})
</script>
不同文件下的局部注册
在一个test.vue中
<template>
<zuname>{{ length }}</zuname>
</template>
<script>
export default {
name: "zuname", //组件名
props: { //父传子 子组件接收内容
length: {
//期待父类传递过来的数据和类型
type: Number,
},
},
};
</script>
主.vue中需要接收子组件
<div id="id">
<zuname :length="length"></zuname>
</div>
import zuname from "./test.vue";//引入子组件
export default {
name: "App", // 在主vue里面可写可不写
data() {},// 方法
methods:{}, //函数方法
computed: {},//计算属性
components: {//局部注册
zuname
}
7 slot插槽
定义一个插槽,就是一个预留的空间,是放使用组件时,标签中间写的内容。
1 solt之匿名插槽
此插槽没有名字,叫匿名插槽。
在组件标签之间可以写内容,你写的内容会放到插槽中。
插槽的作用:在组件变的非常灵活。
<div id="app">
<!-- 在组件标签之间可以写内容,你写的内容会放到插槽中 -->
<component-a>
<h1>我是一个h1标签</h1>
</component-a>
</div>
下方写了slot,上方才会显示组件标签之间的内容。
<template id="temp">
<div>
<div>
<slot></slot>//加上这个就可以插入内容
</div>
</div>
</template>
一个不带 name 的<slot>
出口会带有隐含的名字“default”。
2 solt之具名插槽
在向具名插槽提供内容的时候,我们可以在一个 <template>
元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:
<div id="app">
<!-- 向具名插槽中插入内容的写法有很名 -->
<component-a>
<!-- 通过template给不同的插槽插入不同的内容 -->
<!-- <template v-slot:main> 写法1-->
<template #main><!--写法2-->
<h1>Main</h1>
</template>
</component-a>
</div>
<!-- 下方写了slot,上方才会显示组件标签之间的内容。 -->
<template id="temp">
<div>
<div>
<!-- 如果给一个插槽添加一个name属性,这个插槽就是具名插槽 -->
<slot name="main"></slot>//加上这个就可以插入内容
<!-- <slot>Submit</slot>如果没有给插槽插入数据,可以给插槽指定默认值 -->
</div>
</div>
</template>
现在<template>
元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template>
中的内容都会被视为默认插槽的内容。
3 作用域插槽
插入的内容默认是不能使用username,因为vue规定,一个组件不能使用另一个组件中的数据。
想在插入的内容中使用组件的状态,此时就需要使用作用域插槽。
<div id="app">
<!-- 使用作用域插槽第一步:在使用组件时,使用v-slot指令 -->
<!-- v-slot后面的名字随便写 -->
<current-user v-slot="abc">
<!-- 插入的内容默认是不能使用username,因为vue规定,一个组件不能使用另一个组件中的数据 -->
<!-- {{ username }} -->
<!-- 就想插入的内容中使用组件的状态,此时就需要使用作用域插槽 -->
hello:{{ abc.myusername }}
</current-user>
</div>
<script>
// 如果没有给插槽插入数据,可以给插槽指定默认值
Vue.component("current-user",{
template:`
<div>
<h3>模板中直接使用数据:{{username}}</h3>
<slot v-bind:myusername="username"></slot>
</div>
`,
data(){
return{
username:"wc"
}
}
})
var app = new Vue({
el: '#app',
data: {
name:"wangcai"
},
methods:{
f1(){
console.log("f1.....");
}
}
})
</script>
动态组件
:is=“在绑定的数据”
指定它是什么组件,它就后就渲染成什么组件
<div id="app">
<component :is="com"></component>
</div>
<script>
Vue.component("ComA",{
template:"<div>A组件</div>"
})
Vue.component("ComB",{
template:"<div>B组件</div>"
})
var app = new Vue({
el: '#app',
data: {
com:"ComB"//选择哪个组件就使用哪个组件
},
</script>
keep-alive
把组件缓存起来 组件中的状态都被保留下来了。而不是每次切换导致刷新界面(组件之间的跳转会销毁之前的组件),会影响性能,尤其是针对列表数据较多的情况下,这样再打开就会使用刚缓存起来的组件。可以配合上方动态组件。
<keep-alive>
<component :is="getCurrentTab"></component>
</keep-alive>
路由中判断是否需要缓存
<router-view v-if="!$route.meta.isAlive"></router-view>
<keep-alive>
<router-view v-if="!$route.meta.isAlive"></router-view>
</keep-alive>
强制更新
针对通过索引去修改data中的响应式数据。
如果你是通过索引来修改的数据,数据会改变,但是界面不刷新。
另外,你通过length属性来修改数据,也不会更新。
methods:{
fn(){
this.arr[0] = "xiaoqiang";
// 项目中基本不上会用
this.$forceUpdate(); // 强制让界面刷新
}
}
8 混入
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被 混合 进入该组件本身的选项。
全局混入
混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。
推荐将其作为插件发布,以避免重复应用混入。
// 全局混入 会东西混入到所有的组件中
Vue.mixin({
// 组件里面怎么写,你的混入怎么样
data() {
return {
username: "wangcai"
}
},
methods: {
f1() {
console.log("混入对象中的f1方法......");
}
},
})
Vue.component("comm", {
template: `
<h1>comm组件------{{username}}<button @click="f1">点我</button></h1>
`,
methods: {
fn() {
console.log("233");
}
}
})
let vm = new Vue({
el: '#app',
data: {
msg: "hhhhhhhhh vue",
username: "xxx"//
},
})
局部混入
<div id="app">
{{msg}}
</div>
<script>
// 定义一个混入对象
let myMixin = {
data(){
return{
a:1
}
},
created(){
console.log("混入对象的created");
this.hello()
},
methods:{
hello(){
console.log("hello from mixin")
}
}
}
var app = new Vue({
el: '#app',
data: {
msg:"hello vue"
},
mixins:[myMixin]// 混入对象 把上面的内容混入根实例中
})
</script>
Vue.extend + $mount
<div id="app">
</div>
let compa = {
template:"<div>我是compa组件-----</div>"
}
// Vue.extend 返回的是一个构造器 这个构造器是继承Vue Vue是父类 Component是子类
let Component = Vue.extend(compa)
// new Component得到一个组件
// abc是一个组件 实例
let abc = new Component();
abc.$mount("#app")
render函数
在script可以写模板。
render是一种渲染函数,优化模板内容,更简洁。
<div id="app">
<anchored-heading :level="1">hello render函数</anchored-heading>
</div>
<!-- 在定义组件时,直接使用模板的方式,有时候,也不灵活,此时就可以使用render函数 -->
<!-- 也是定义模板的一种方式 -->
<script type="text/x-template" id="anchored-heading-template">
<div>
<h1 v-if="level === 1">
<slot></slot>
</h1>
</div>
</script>
Vue.component("anchored-heading",{
template:"#anchored-heading-template",}
============================================================================
Vue.component("anchored-heading",{
render(h){ // h ===> createElement
// h也是一个函数
return h(
"h"+this.level, // tag name 标签名称
this.$slots.default // 子组件中的阵列
)
},