这篇是用 markdown 写的,建议下载一个markdown阅读器 typora,方便阅读。
公司前端项目基本都用的Vue全家桶:
- 路由管理:Vue-Router,官方文档写的很清晰。
- 数据请求:双控用的Axios、另外有一些项目用的 Vue-Resource。
- 状态管理:Vuex,目前只有双控项目用到了,官方文档教程写的很清晰,需要花费时间去学习。
- UI框架使用的Element-UI,注意老项目Element版本不同配置方法。
- 依赖包管理:基本用的是yarn, 最好别和npm一起混用。
- css预处理器:sass,sass可以做很多事情,变量、继承、函数、Mixin、运算、循环等、熟练了写起样式会很高效,官方文档教程也讲的很清晰。这是我收藏的几个CSS网站 css-tricks css3-generator gradient box-shadow,能够快速的生成一些好看的CSS效果。
可以学一下 ES6 语法,解构赋值、对象的 assign、 展开操作符 、属性名简洁表示、async await 等一些经常会用到。有空的话可以了解下正则(JavaScript 正则表达式迷你书),最近经常能用到。
下面的这些是我在刚开始学习Vue基础部分时做的笔记,整合删改了一些,又添加了一部分示例,基本涵盖了Vue基础知识,供参考,也可以直接看官方文档的教程。我学习Vue时主要也是通过官方文档,把基础部分过一遍,示例代码手敲自己运行一下,刚开始可以先不深究原理,先掌握基础用法,在项目中碰到看不懂的代码再去查阅文档或请教恒哥。
Vue基础知识部分
构造器
- 实例化vue时,需传入一个选项对象,它可以包括 数据、模板、挂载元素、方法和生命周期钩子
属性与方法
- 每个vue实例都会代理其data对象里所有的属性
- vue实例暴露了一些有用的实例属性与方法,这些属性与方法都有前缀$,以便与代理的data属性区分
实例生命周期
- created钩子——在实例被创建后被调用
- mounted—-当编译好的HTML被挂载到对应的位置,这个操作完成后触发
- updated—-当data中的数据改变,并且虚拟DOM重新渲染完成后触发
- destroyed
- 概要: 钩子的this 指向调用它的实例
生命周期图示
插值
- 文本
- 双大括号
- v-text
- 纯HTML
- v-html
- 属性
- v-bind(大双括号不能在属性中使用,因此需使用v-bind)
- 使用JavaScript表达式
指令
哪些指令?
- v-bind
- v-on
- v-if
- v-for(特殊)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26v-if
<div id="app">
<template v-if="ok==='username'">
用户名: <input type="text" placeholder="请输入用户名" key="name-input">
</template>
<template v-else>
密码: <input type="text" placeholder="请输入密码" key="psd-input">
</template>
<button @click="toggle">点击切换类型</button>
</div>
new Vue({
el: "#app",
data: {
ok:'username'
},
methods: {
toggle: function(todo){
if(this.ok==='username'){
this.ok = 'psd'
}else{
this.ok = 'username';
}
}
}
})1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18v-for
<div id="app">
<ul>
<li v-for="item in items">{{item}}</li>
</ul>
</div>
new Vue({
el: "#app",
data: {
items:['a','b','c']
},
methods: {
toggle: function(todo){
todo.done = !todo.done
}
}
})修饰符
过滤器
过滤器的目的是用于文本转换,转化成你想要的格式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26filters
<div id="app">
<p>{{message | changeChar}}</p>
<button @click="changeFirstChar">改变</button>
</div>
new Vue({
el: "#app",
data: {
message:'nihao'
},
methods: {
changeFirstChar: function(todo){
this.message = 'good evening'
}
},
filters:{
changeChar(value){
if(!value){
return '';
}else{
return value.charAt(0).toUpperCase()+value.substring(1)
}
}
}
})
缩写
计算属性
计算属性(减少模板的复杂度)
- 计算属性的基础写法
1 | computed |
计算缓存vs方法(Methods)
- 计算属性computed具有缓存,而methods无缓存
Computed属性vs 侦听器(Watch属性)
- watch方法–观察Vue实例上的数据变动,只要指定的数据改变就会执行预定的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25watch
<div id="app">
{{msg}} <br>
改变了吗? {{isChange}}
<button @click="change">改变</button>
</div>
new Vue({
el: "#app",
data: {
msg:'111',
isChange:'No'
},
watch:{
//只要msg改变,这个方法就会执行
msg(val,oldVal){
this.isChange = 'Yes'
}
},
methods:{
change(){
this.msg = '222'
}
}
})- computed方法
计算setter 和getter
- get和set,顾名思义,一个是获得,一个是设置,常规上来讲,计算属性中都是有get和set方法的,默认是只有getter方法,如果需要的话,自然可以写一个setter方法.
1 | get和set |
class与style绑定
绑定HTML class
对象语法
- 基本
- 在对象中传入多个class属性(其会与原有class共存)
- 直接传入对象
- 与计算属性一起使用(绑定返回对象的计算属性)
数组语法
- 简单例子
- 三元表达式
- 当有多个条件class时,可以在数组语法中使用对象语法
用在组件上
- 简单例子
- 绑定HTML class例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19绑定class的几种方式
.classC{
color:red;
}
.classD{
font-weight:bold;
}
.classE{
font-size:20px;
}
.classF{
color:blue;
}
.classM{
display:block;
}
.classN{
display:none;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<div id="app">
<h2>class属性绑定</h2>
-------------------绑定变量-------------------------
<div :class="{classA:a,classB:b}">
绑定变量
</div>
-------------------绑定对象-------------------------
<div :class="styleObj">
绑定对象
</div>
-------------------绑定数组-------------------------
<div :class="arrClass">
绑定数组
</div>
-------------------绑定三元运算符-------------------------
<div :class="m==true?'classM':'classN'">
绑定变量
</div>
<button @click="toggle">toggle</button>
</div>
1 | new Vue({ |
绑定内联样式
- 对象语法
- 内联式对象语法
- 样式对象式对象语法(更推荐)
- 数组语法
- 自动添加前缀
- v-bind:style 当需要特定的前缀时如transform,vue.js会自动添加
- 多重值
- 可以为一个属性添加多个值的数组,常用于含有多个前缀的情况
条件渲染
v-if(v-else)是真正的渲染
template元素与v-if
v-else(需要紧跟在v-if后边)
v-else-if
用key管理可复用的元素
- 例子:用户名和邮箱登录界面 如果有key就不会复用,可以把key去试一下,然后输入看一下效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25<div id="app">
<template v-if="ok==='username'">
用户名: <input type="text" placeholder="请输入用户名" key="name-input">
</template>
<template v-else>
密码: <input type="text" placeholder="请输入密码" key="psd-input">
</template>
<button @click="toggle">点击切换类型</button>
</div>
new Vue({
el: "#app",
data: {
ok:'username'
},
methods: {
toggle: function(todo){
if(this.ok==='username'){
this.ok = 'psd'
}else{
this.ok = 'username';
}
}
}
})
v-show(其只是简单的切换display属性)
- v-show不支持template语法
- v-show不支持v-else
v-if VS v-show
- v-if
- 当条件不成立时不会渲染
- 切换开销较大,适合不太可能变化的场景
- v-show
- 无论成不成立都会渲染
- 首次渲染开销较大,但切换开销小,因此适合经常变化的场景
列表渲染
v-for
- 基本用法
- 简单例子
- 带有index参数
- 使用of 替代 in
- template v-for
- 简单例子
- 对象迭代 v-for
- 基础用法
- 带其他参数用法
- 整数迭代 v-for
- 例子
- 组件和v-for
包含所有类型的例子
1 | <template> |
key
作用
- 用v-for更新已渲染过的列表时,它默认采用的是“就地复用”的原则,也就是如果数据项顺序发生了改变,vue将不是移动DOM元素来匹配数据项的顺序,而是简单复用此处的元素。如果想跟踪每个节点的身份,从而重用或重新排列现有元素,可使用key。
key有什么用,
1
2
3
4
5
6
7
8
9
10<div id="app">
KEY: <input type="text" v-model="id"> VALUE: <input type="text" v-model="name">
<button @click="add">添加</button>
<ul>
<li v-for="item in list" :key="item.id"> //此处你可以吧key去了,先勾选一条,在追加一条试一下,然后加上key,勾选一条追加一条再试一下,一目了然
<input type="checkbox" >
{{item.id}}---{{item.name}}
</li>
</ul>
</div>
1 | new Vue({ |
因为加上key默认采取的就是就地复用策略
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
### 数组更新检测
- 变异方法(会改变原有数组)
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
- 重塑数组
- filter()
- concat()
- slice()
- 注意事项
利用索引直接设置一个项时,vue不能检测变动,如:vm.items[indexOfItem] = newValue
如果要设置某一项
- Vue.set(example1.items, indexOfItem, newValue)
example1.items.splice(indexOfItem, 1, newValue)
1
2
—
var vmm = new Vue({
el: “#app”,
data: {
id:””,
name:””,
list:[
{id:1, name:’李斯’},
{id:2, name:’嬴政’},
{id:3, name:’赵高’},
{id:4, name:’韩非’},
{id:5, name:’荀子’},
]
},
methods: {
setZF: function(){
Vue.set(this.list,1,{id:2,name:’张飞’})
},
setGY:function(){
this.list.splice(2,1,{id:3,name:’关羽’})
}
}
})
1 |
- 修改数组长度时,vue不能检测变动,如:vm.items.length = newLength
- 只能用example1.items.splice(newLength)
1 |
|
计算属性应用于过滤
new Vue({
el: “#app”,
data: {
nums:[1,2,3,4,5,6,7,8,9]
},
computed:{
specialNum(){
return this.nums.filter((item,index)=>{
return item%3==0;
})
}
}
})
1 |
//在v-for循环中直接嵌入方法
new Vue({
el: “#app”,
data: {
numbers:[1,2,3,4,5,6,7,8,9]
},
methods:{
fil(nums){
return nums.filter((item,index)=>{
return item%3==0;
})
}
}
})
1 |
|
1
2
new Vue({
el: “#app”,
methods: {
sayHello: function(){
alert(‘sayHello’)
}
}
})
1 |
|
new Vue({
el: “#app”,
data: {
msg:’’
},
methods: {
showBtnname: function(e){
this.msg = e.target.innerText;
}
}
})
1 |
|
—————————-html———————————
Todos:
<del v-if="todo.done">
{{ todo.text }}
</del>
<span v-else>
{{ todo.text }}
</span>
</label>
</li>
</ol>
—————————-js———————————
new Vue({
el: “#app”,
data: {
todos: [
{ text: “Learn JavaScript”, done: false },
{ text: “Learn Vue”, done: false },
{ text: “Play around in JSFiddle”, done: true },
{ text: “Build something awesome”, done: true }
]
},
methods: {
toggle: function(todo){
todo.done = !todo.done
}
}
})
—————————-css———————————
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
1 |
|
new Vue({
el: “#app”,
data: {
num:0
}
})
1 |
|
new Vue({
el: “#app”,
data: {
msg:’万年的msg’
}
})
1 |
|
1 |
|
<div id="app">
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
</div>
new Vue({
el: "#app",
data: {
checked:true
}
})
1
2
- 多个复选框(将选中的所有value绑定到一个数组)
<div id="app">
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
{{checkedNames}}
</div>
new Vue({
el: "#app",
data: {
checkedNames:[]
}
})
1
2
- 单选按钮(绑定选中的单选框的value)
Picked:
new Vue({
el: “#app”,
data: {
picked:’’
}
})
1 |
|
<div id="app">
<select v-model="selected">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
new Vue({
el: "#app",
data: {
selected:''
}
})
1
2
- 多选列表(绑定一个数组,数组的内容是所有的选中项的value)
<div id="app">
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Selected: {{ selected }}</span>
</div>
new Vue({
el: "#app",
data: {
selected: []
}
})
1
2
- 动态选项
<div id="app">
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
new Vue({
el: "#app",
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
1
2
3
4
5
6
### 修饰符
- .lazy
- 由原有的input事件变更为change事件
<div id="app">
<input type="text" v-model.lazy="msg">
{{msg}}
</div>
new Vue({
el: "#app",
data: {
msg:'万年的msg'
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- .number
- 将输入的类型转换成数字类型(NaN则还是原有类型)
- .trim
- 去除两端空白
### v-model与组件
## 组件
### 使用组件
- 注册
- 注意事项
- 在初始化根实例前一定要确保注册了组件!!!!
- 名称最好 小写(可以使用短杆)
<div id="app">
<my-comp></my-comp>
</div>
Vue.component('my-comp',{
template:'<h3>我是新出炉的组件</h3>'
})
new Vue({
el: "#app",
data: {
}
})
1
2
- 局部注册
new Vue({
el: “#app”,
components:{
‘my-comp’:{template:’
我是新出炉的组件
‘}},
data: {
}
})
1 |
|
<div id="app">
<table>
<tr>
<my-comp></my-comp>//注意:这样写是绝对错误的,因为tr中只允许有td,这样写他是不认识滴
</tr>
</table>
</div>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 上边是错误的
---------------------------------下边是正确的-----------------------------------
<div id="app">
<table>
<tr>
<td is="my-comp"></td>
</tr>
</table>
</div>
new Vue({
el: "#app",
components:{
'my-comp':{
template:'<td>我是组件td</td>'
}
},
data: {
}
})
1
2
3
4
- 不受限的情况--使用字符串模板
- <script type="text/x-template"> 怎么用呢?给大家来个例子吧!
-------------------------------HTML-----------------------------------------
<div id="app">
<table>
<tr>
<template>
<my-comp></my-comp>
</template>
</tr>
</table>
</div>
<script type="text/x-template" id="myComponent">
<td>This is a component!</td>
</script>
-----------------------------------JS----------------------------------
new Vue({
el: "#app",
components:{
'my-comp':{
template:'#myComponent'
}
},
data: {
}
})
1
2
- JavaScript内联模板字符串(什么是字符串模板)
<div id="app">
<table>
<tr>
<template> //这个就是字符串模板
<my-comp></my-comp>
</template>
</tr>
</table>
</div>
1
2
3
4
- .vue组件 (第三种)
- data必须是函数,在组件中使用data中定义的数据,必须使用函数返回,我自己的理解,最根本的三个字就是作用域,目的就是为了防止组件中使用的data和vue实例中的data进行相互污染,
<div id="app">
<mycomp></mycomp>
</div>
new Vue({
el: "#app",
components:{
'mycomp':{
template:'<button>{{btncount}}</button>',
data(){
return {btncount:8}
}
}
},
data:{
btncount:10
}
})
1
2
3
4
### Prop(子组件从父组件获得数据)
- 使用prop传递数据
<div id="app">
<child msg="我是来自于父组件的内容"></child>
</div>
new Vue({
el: "#app",
components:{
'child':{
props:['msg'],
template:'<h2>{{msg}}</h2>'
}
}
})
1
2
动态绑定父组件中的数据
<div id="app">
<input type="text" v-model="fathertext">
{{fathertext}}
<child :childText="fathertext"></child>
</div>
new Vue({
el: "#app",
components:{
'child':{
props:['childtext'],
template:'<h1>{{childtext}}</h1>'
}
},
data: {
fathertext:''
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-
- props注意事项
- 一般情况下是数组形式,如果要想规定props的数据类型(后面用中括号 [ ])。默认值等(props验证),则是对象了(后面用花括号 { })
- 关于命名:要不然全小写,要不然kebabCase(驼峰式),kebab-case(短横线隔开式)Vue 能够正确识别出小驼峰和下划线命名法混用的变量,如这里的`forChildMsg`和`for-child-msg`是同一值。
- 动态Prop(使用v-bind):在模板中,要动态地绑定父组件的数据到子组件模板的 props,和绑定 Html 标签特性一样,使用v-bind绑定
- 局部注册组件
- 全局注册组件
- 字面量语法vs动态语法
- 单向数据流
- 解释
- 父组件数据更新后,子组件的所有prop都会更新为最新值,但是反过来就不会。(注意 :如果prop为数组或对象时,子组件改变prop,父组件的状态也会受到影响,因为数组或对象是引用类型,他们指向同一个内存空间。)如果子组件的prop值被修改,则vue会给出警告。
<div id="app">
<parent></parent>
</div>
let childNode = {
template: `
<div class="child">
<div>
<span>子组件数据</span>
<input v-model="forChildMsg"/>
</div>
<p>{{forChildMsg}}</p>
</div>`,
props: {
"for-child-msg": String
}
};
let parentNode = {
template: `
<div class="parent">
<div>
<span>父组件数据</span>
<input v-model="msg"/>
</div>
<p>{{msg}}</p>
<child :for-child-msg="msg"></child>
</div>
`,
components: {
child: childNode
},
data() {
return {
msg: "default string."
};
}
};
new Vue({
el: "#app",
components:{
parent:parentNode
}
})
1
2
3
4
5
6
- 特殊情况应对方法
- prop作为初始值传入后,可能子组件想把它当做局部数据来用的情况
- 方法:定义一个局部变量,并用prop的值初始化它
props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}
//直接使用counter作为子组件的局部变量就可以了
1
2
3
4
- prop作为初始值传入,可能子组件处理成其他数据输出的情况,比如处理成去空格并大写
- 方法:定义一个计算属性,处理prop的值并返回
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
1
2
3
4
- prop验证
- 例子
Vue.component('example', {
props: {
// 基础类型检测 (`null` 意思是任何类型都可以)
propA: Number,
// 多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数字,有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}
})
1
2
3
4
5
6
7
8
### 自定义事件(子组件将数据传回父组件)
- 使用v-on绑定自定义事件
- 给组件绑定自定义事件例子(用v-on来监听子组件触发的事件)
- 给组件绑定**原生事件**例子--使用native修饰符
<div id="app">
<btncomp @click.native="alertE"></btncomp>
</div>
new Vue({
el: "#app",
components:{
btncomp:{
template:'<button>点击我弹出</button>'
}
},
methods:{
alertE(){
alert(777)
}
}
})
1
2
3
4
5
6
- .sync修饰符
- 目的:使父子组件实现prop类似“双向数据绑定”(默认子组件无法更改prop的值,上边已经说到了,但是使用sync后子组件可以改变prop 的值,并传回父组件)
- 使用范例
<div id="app">
<child :name.sync="name"></child> //其实不加也能更改,但是会报错
<button type="button" @click="changePropsInFather">在父组件中将props值改变为'props'</button>
</div>
Vue.component('Child', {
template: `<h1 @click="changePropsInChild">hello, {{name}}</h1>`,
props: {
name: String,
},
methods:{
changePropsInChild(){
this.name = 'I am from child'
}
},
})
// 实例化一个Vue对象
const app = new Vue({
el: '#app',
data(){
return {
name: 'world'
}
},
methods:{
changePropsInFather(){
this.name='I am from father'
},
},
})
1
2
3
4
5
6
- 使用自定义事件的表单输入组件
- v-model的语法糖
v-model只是一个语法糖,它的真身是下边这样:
<div id="app">
<input type="text" :value="price" @input="price = $event.target.value">{{price}}
</div>
new Vue({
el: '#app',
data: {
price: ''
}
});
1
2
3
4
- 例子
- html及实例部分和注册组件部分
<div id="app">
<price-input :value="price" @input="isinputing"></price-input>
{{price}}
</div>
new Vue({
el: "#app",
components:{
'price-input':{
template:"<input type='text' @input='update($event.target.value)' />",
props:['value'],
methods:{
update(val){
this.$emit('input',val)
}
}
}
},
data: {
price:''
},
methods: {
isinputing: function(val){//此处的value就是子组件传递过来的
this.price = val;
}
}
})
1
2
3
4
5
6
### 非父子组件通信
- 非父子组件通信(1 父传子是用props 2 子传父在vue中是不允许的,因为vue只允许单向数据传递,这时候我们可以通过触发事件来通知父组件改变数据,从而达到改变子组件数据的目的.
- 简单的场景---采用空实例作为中央事件总线(EventBus),原理就是找一个人来当作一个中转站!
<div id="app1" @click="toApp2">
我是组件一,点击我给二传值
</div> <br>
<div id="app2">
{{app2msg}}
</div>
var bus = new Vue(); // 创建事件中心,创建中转站
new Vue({
el: "#app1",
data: {},
methods: {
toApp2: function(){
bus.$emit('change','上山打老虎') //使用中转站触发
}
}
})
new Vue({
el: "#app2",
data: {
app2msg:''
},
created(){
bus.$on('change',(val)=>{
this.app2msg = val; //在组件二创建完成的时候就使用中转站进行监听
})
}
})
1
2
3
4
5
6
7
8
- 复杂的场景---专门的状态管理模式vuex
### 使用Slot分发内容
- 内容分发概念
- 为了让组件可以组合,因此需要混合父组件的内容与子组件的自己模板,这一过程就称作内容分发。
<app>
<app-header></app-header>
<app-footer></app-footer>
</app>
如果给app指定了模板,那么里边的app-header和foot组件的内容就会被覆盖,因此,为了让他们能够组合.需要混用,这就是内容分发
1
2
3
4
5
6
7
8
9
10
- 编译作用域
- 分发内容是在父作用域内编译的
- 单个slot(无具名slot)
- 为什么用slot
- 当父组件中有内容子组件模板中无slot时,则父组件中的内容会被丢弃。
<div id="app">
<my-comp>
<p>我是组件中的内容</p> //这个p会被覆盖
</my-comp>
</div>
new Vue({
el: "#app",
components:{
'my-comp':{
template:'<h1>我是一个组件</h1>'
}
}
})
1
2
单个slot怎么用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<div id="app">
<children>
<span>12345</span>
<!--上面这行不会显示-->
</children>
</div>
var vm = new Vue({
el: '#app',
components: {
children: { //这个无返回值,不会继续派发
template: "<button><slot></slot>(我是button)</button>"
}
}
});
1 |
|
<div id="app">
<children>
<span slot="first">12345</span>
<span slot="second">56789</span>
<!--上面这行不会显示-->
</children>
</div>
var vm = new Vue({
el: '#app',
components: {
children: { //这个无返回值,不会继续派发
template: "<button><slot name='first'></slot>我是button<slot name='second'></slot>所以使用button标签</button>"
}
}
});
说白了,就是多一个name属性
1
2
3
4
5
6
7
8
- 作用域插槽(特殊的插槽)
- 作用:使用可复用模板替代已渲染元素
- 用法:同具名slot类似,都是严格按照子组件的模板顺序渲染,**只不过遇到slot元素时会将父组件中的template元素里的元素全部渲染**
- 列表组件例子
<div id="app">
<child :items="items">
<template slot="item" scope="props">
<!--必须存在的具有 scope属性的 template元素(作用域插槽的模板),
props临时的变量名称,接受子组件中传递的props对象-->
<!--slot = “item”是具名 slot的用法。-->
<li>
{{props.tex}}
<!--引用子组件中绑定的tex属性值。-->
</li>
</template>
</child>
</div>
Vue.component('child',{
props:["items"],
template:'<ul><slot name="item" v-for="item in items" v-bind:tex="item.text"></slot></ul>'
});
new Vue({
el:'#app',
data:{
items:[
{text:'h'},
{text:'y'},
{text:'z'}
]
}
})
1
2
3
4
### 动态组件
- 使用is属性(注意,is前使用了v-bind!!!通过**is**来决定那个组件被渲染显示 )
var app=new Vue({
el:'#app',
data:{
show:'tem1'
},
components:{
tem1:{
template:'<div>11111111111</div>'
},
tem2:{
template:'<div>22222</div>'
},
tem3:{
template:'<div>333333</div>'
}
},
methods:{
changeShow:function(){
if(this.show=='tem1'){
this.show='tem2'
}else if(this.show=='tem2'){
this.show='tem3'
}else{
this.show='tem1'
}
}
}
})
1 |
|
<div id="app">
<component v-bind:is="show"></component>
<button v-on:click="changeShow">change show</button>
</div>
var app=new Vue({
el:'#app',
data:{
show:'tem1'
},
components:{
tem1:{
template:'<div>11111111111</div>'
},
tem2:{
template:'<div>22222</div>'
},
tem3:{
template:'<div>333333</div>'
}
},
methods:{
changeShow:function(){
if(this.show=='tem1'){
this.show='tem2'
}else if(this.show=='tem2'){
this.show='tem3'
}else{
this.show='tem1'
}
}
}
})
```