Vue学习笔记
学习的尚硅谷的网课
Vue是什么
Vue是用于构建用户的渐进式框架,其特点有
- 组件化模式:提高复用率,让代码更好维护
- 声明式编码:无需直接操作DOM
- 虚拟DOM和Diff算法
容器和Vue实例的关系是1对1的,真实开发中只有一个Vue实例,配合着组件进行使用
双向绑定:一般用于表单元素上,#重要概念-Vue#v-model:value可以简写为v-model,因为v-model默认收集的就是value值
可以使用el或者$mount(' ')进行挂载容器,$mount(' ')会更为灵活
data的两种写法:对象式和函数式,在组件中使用必须使用函数式
数据代理
Object.defineProperty() - JavaScript | MDN (mozilla.org)
Object.definProperty()方法会直接在对象上定义一个新属性,或者修改已有的属性,并返回此对象
参数:(对象,’属性名',要定义或修改的属性描述符「对象」),默认状态下,通过此方法定义的对象属性不可枚举,如果想要进行枚举,就要在第三个对象参数中添加 enumerable:true,默认属性值是不可进行修改的,使用writable:true解除修改限制,默认属性值不可以进行删除,使用configurable:true解除删除限制
如果我们想让对象的某个值随着外部变量的变化而变化该怎么办呢?
我们希望 student 对象中的 age 属性跟随着外部的 number 变量的变化进行变化
let number = 20;
const student = {
name:'张三',
sex:'男'
}
Object.defineProperty(student,'age',{
//利用此方法的getter,getter会在获取这个这个对象属性的行为发生时,通过gettert返回出去
get(){
return number;
},
//利用此方法的setter,setter会在修改这个对象的属性的行为发生时,调用set里面的方法,被修改的值会成为setter的第一个参数,如果想要
// age 跟随这 外部变量 number 变化,则在set里面将 value 的值赋值给 number
set(value){
number = value;
}
})
数据代理
定义:通过一个对象中的变化去修改另一个对象中的变化,叫做数据代理
下面代码就是通过 obj 和 obj2 数据实现了代理
const obj = {x:100}
const obj2 = {y:200}
Object.defineProperty(obj2,'x',{
get(){
return obj.x;
},
set(value){
obj.x = value;
}
})
Vue中的数据代理
Vue的数据是响应式的,是利用了数据劫持和数据代理进行写的,这边我们只讨论数据代理,我们新建了一个 Vue 实例vm 我们在vm的 data 对象中定义的属性,会在vm本身生成一个相同的属性,data对象中的数据存放在了 vm._data 这个属性中,他们属性的修改和获取都会使得双方的数据发生改变,但是要实现响应式变化,就要进行数据劫持,监听数据的变化,这边不讨论
const vm = new Vue({
data:{
name:"白德培",
adress:'山东省'
}
}).$mount('#app')
键盘事件与修饰符
键盘事件有两种:keydown :按键按下就触发 和 keyup:按键按下抬起后触发
在vue中,可以通过v-on绑定键盘事件后跟事件修饰符进行检测,vue中为常用的按键起了别名,这些内置的别名可以兼容不同的规范
-
.enter -
.tab:tab比较特殊,因为tab本身就拥有切换元素的功能,所以在使用tab的时候,使用keydown事件居多 -
.delete (捕获“删除”和“退格”键) -
.esc -
.space -
.up -
.down -
.left -
.right -
系统修饰符:在使用系统修饰符时,如果是
keyup事件,只会在按住修饰符的时候按下其他任意键进行触发。使用keydown时则不会,使用链式修饰符可以指定按键,比如@keyup.ctrl.y='方法',只有按下ctrl+y的时候才会触发方法.shift.meta.alt.ctrl
当然除了这些别名也可以写按键的 key 值
但是如果是像CapsLock这种按键,在事件修饰符中应该写成 caps-lock
你还可以通过全局 config.keyCodes 对象自定义按键修饰符别名:Vue.config.keyCodes.f1 = 112,在使用时就可以
修饰符
修饰符可以连续写
.stop:阻止冒泡行为
.once:事件只触发一次
.prevent:阻止默认行为
v-model的修饰符:.number 以数字类型进行存储
计算属性
类型:{ [key: string]: Function | { get: Function, set: Function } }
计算属性也是根据数据代理去修改的,也可以设置自己的 setter 和 getter, 但是计算属性更多的时候只是用于显示,如果想要单独设置set也是可以的,只不过要写成对象形式,就像数据代理那样,,如果直接写成函数形式,默认就是getter
计算属性只有在数据更新的时候才会进行重新计算
侦听器
watch 使用与变量名重名的函数或者对象或者计算属性进行定义
//假设要监听 isHot 属性的变化,是个Boolean
watch:{
isHot:{
handler(newData,oldData){
//handler会做为 isHot 发生变化时执行的函数,他的两个参数会记录下来变更前和变更后数值
},
immediate: Boolean, //immediate 翻译为立即,默认值为false,如果为true,则在程序启动时调用一次handler
}
}
也可以使用vm.$watch('变量...',{配置项})进行数据侦听
Vue默认是可以检测到多层级的数据改变的,但是Vue提供的watch中是检测不到多层级数据改变的
watch中的属性是简写的,比如watch:{ isHot:{ } },isHot是以字符串的形式存在的,如果有个number对象中的属性a,要对这个a进行侦听的话,就要写为watch:{ 'number.a':{ } }
如果number对象拥有多个属性,现在要对number这个对象进行侦听,对象中任意一个属性发生变化就会触发侦听器,就要使用深度侦听
numbers:{
deep:true,
handler(newData,oldData){
console.log(``);
}
}
但是这侦听会失去具体的数值变化,他只会提示你这个对象的变化,但是不会提示你对象属性值的具体变化
当侦听器不需要立即执行功能和深度侦听功能时,可以简写为函数的形式
//实例中创建watch形式
watch:{
isHot(newData,oldData){
console.log(newData,oldData)
},
}
}
//调用API形式
vm.$watch('isHot',function(newData,oldData){console.log(newData,oldData)})
watch和computed的区别
- 计算属性能完成的事情,watch都可以完成
- watch能完成的功能,计算属性不一定能完成,例如 watch可以进行异步操作
绑定Class和Style
绑定class和style都可以使用:字符串写法、对象写法、数组写法、数组中对象写法、计算属性写法
原文链接1
Class
对象语法
<style> .active { color: red; } .active-font { font-size: 2em; } </style><body> <div id="app"> <span :class="{ active:isactive, 'active-font':isactiveFont}"> 这是用来测试class与style绑定的文字 </span> </div> const App =new Vue({ el:'#app', data:{ isactive:true, isactiveFont:true, }, computed:{ }, component:{}, }); 使用对象进行添加的时候,有短横杠的类使用
''包起来,比如上面的active-font类,在写的时候使用'active-font'绑定的数据对象不必内联定义在模板里:
<div v-bind:class="classObject"></div>data: { classObject: { active: true, 'text-danger': false } }也可以绑定一个计算属性
<div v-bind:class="classObject"></div>data: { isActive: true, error: null }, computed: { classObject: function () { return { active: this.isActive && !this.error, 'text-danger': this.error && this.error.type === 'fatal' } } }数组语法
我们可以把一个数组传给
v-bind:class,以应用一个 class 列表:<div v-bind:class="[activeClass, errorClass]"></div>data: { activeClass: 'active', errorClass: 'text-danger' }如果你也想根据条件切换列表中的 class,可以用三元表达式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>这样写将始终添加
errorClass,但是只有在isActive 是 truthy(真值)[1]^^ 时才添加activeClass。不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
收集表单数据
常用的表单元素有
input 输入框
input type='radio' 单选框,name要相同
input type='checkbox' 多选框,name要相同,需要使用数组接受value值
select->option 下拉菜单
textarea 文本域
过滤器
使用filters:{}进行表示,过滤器中使用函数标识,在使用中{{ time | getformattime }},通过管道符进行连接,可以连接多个过滤器,顺着管道向下传参,最终这个插值模板中会显示过滤器返回的值,过滤器的第一个参数始终是使用的变量
v-cloak属性
cloak:翻译隐藏,v-cloak属性在加载Vue实例的时候会自动移除,为了防止js阻塞造成的未渲染,在css中使用属性选择器选择所有的带有v-cloak属性的元素,让他们不显示,当Vue加载完成后,自动移除v-cloak属性
v-once属性
放在标签里面,没有值,使用了v-once的标签如果用了插值,那么这个标签显示的值就是插值的第一个值,之后不会变化
v-pre属性
放在标签中的属性,使用了v-pre的标签不会被Vue解析,加快了Vue解析的过程
自定义指令
在Vue实例中使用directives进行配置,自定义指令什么时候会执行呢?
- 在成功绑定到元素的时候会执行,这时候元素可能并未被解析到页面上
- 在元素所在模板被解析的时候会执行
自定义指令函数式
写法简单,但是不能处理细节
<div id="app">
<h1 v-big="adress"></h1>
</div>
<script>
new Vue({
data:{
adress:'理塘'
},
directives:{
// 自定义指定-函数式
big(element,binding){
element.innerText = binding.value+'丁真'
}
}
}).$mount('#app')
自定义指令对象式
写法复杂,但是能处理细节
相对于函数式,多出来几个固定方法,类似于生命周期
directives:{
fbind:{
bind(){}, //绑定时调用
inserted(){}, //插入完成后调用
update(){} //数据所在的模板重新被解析时调用
}
}
组件化编程
组件是不能绑定元素的!!!!!
VueComponent构造函数
Vue组件的本质是一个名为VueComponent的构造函数,是Vue.extend({ })生成的,VueComponent是负责创造更多的组件模板,
每当写入标签时,就相当于 new 了一个VueComponent的实例对象,所以复用的组件数据是不影响的
每次调用Vue.extend({ })都会生成一个新的VueComponent
VueComponent和Vue在原型链上的关系
复习:原型和原型链2
Vue手动将VueComponent的原型对象指向了Vue的原型对象,这样就能让组件的实例对象去使用Vue原型对象上的方法和属性
组件名命名规范
如果组件是一个单词组成 1.使用首字母小写 school 2.使用首字母大写 School (个人推荐)
如果组件由多个单词组成 1.短横杠写法 ,全小写 my-school 2.首字母大写 MySchool (需要Vue脚手架的支持才能使这种名字的标签解析)
标签的写法 1.成对出现<school> </school> 2.自闭和标签 <school/> (这种写法在非脚手架中,不会对这个自闭和标签后的标签进行解析)
非单文件组件:一个文件中包含了多个组件
组件只能在Vue的实例中去使用
使用Vue.extend({ })创建组件,组件不能去挂载容器,组件中的data只能采用函数式去定义,组件只有注册过才能使用
创建组件可以简写为: const 变量名 = {配置项},在Vue实例中如果使用这个变量作为组件,那么Vue会在注册组件的时候自动的将这个对象变量转化为组件
在Vue实例中的compoents对象中去注册组件
这种方式属于局部注册组件
new Vue({
components:{
自定义组件名:组件实例名, //也可以直接写组件实例的名字,因为这是非单文件的组件
}
})
全局注册组件:使用 Vue.component('自定义组件名',组件实例名)进行全局注册组件
name属性可以决定在开发者工具中显示的组件名字
可以在组件或者Vue实例的$children属性中看到子组件
单文件组件:一个文件中只包含一个组件
遇到的问题
vue根目录下的index.html中的id="app"与src目录下的App.vue中的id="app"为什么不会冲突_RotatingBlock的博客-CSDN博客
Vue 的单文件组件 (即 *.vue 文件,英文 Single-File Component,简称 SFC) 是一种特殊的文件格式,使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中,使用 SFC 必须使用构建工具
在使用脚手架工具后,public文件夹下index.html文件的说明
#🎨Question-Vue:#
App.vue中的<div id='app'>和index.html中的<div id='app'>有什么区别 可去本标题开头查看 遇到的问题中的他人回答,以下是我的总结
Vue组件一定要有一个根元素 div
首先要明确一个问题,App.vue是根组件不是Vue的实例化对象, App.vue也是个组件,只不过是最顶层的组件,在他的上面就是vm,即Vue的实例对象,在「main.js」中我们引入了Vue库,然后去 new 了一个Vue实例对象,通过使用$mount挂载到了「public」下「index.html」中的 app 容器中,这个 app 的容器的作用就是用来绑定元素根路径的,而App.vue中的app容器,是用来想元素根路径去注入内容的,实际被解析出来的只有App.vue的<div id='app'>,而作为index.html中的app只是作为一个解析入口,实际上不会被解析
关于「main.js」中的render函数是什么东西
在「main.js」中引入的Vue,其实是一个阉割版的Vue,这个Vue只保留了Vue的核心功能,去掉了一些模板渲染功能,没有了模板渲染功能,就不能写template,所以需要借助render函数接受到的createElement函数进行创造元素
//这是main.js中的语句
new Vue({
render: h => h(App),
}).$mount('#root')
render是一个函数,他接受一个createElement的函数参数,通过像这个createElement传入组件并返回,可以快速的渲染元素
render(createElement){
return createElement('标签类型',<标签内容>), //这是createElement一种用法,比如下一行
return createElement('h1','这是我渲染的h1标签'), //如果使用这种方式,就会在页面上渲染出一个h1标签,并且有内容
return createElement(组件名), //如果使用这种方式,就会直接解析组件中的template模板
}
因为render函数只有一个参数,并且只返回一个简单的表达式,就可以使用箭头函数简写为
render: h => h(App)
修改CLI的默认配置#🎨Question-Vue:#
像主入口什么的都是可以改的,官方提供了CLI的配置全局CLI配置参考
使用 vue inspect > output.js可以查看到Vue脚手架的默认配置,但可能会出现编码乱码问题,另存为utf-8
在与「package.json」同级目录下新建「vue.config.js」文件,这个文件中的内容应该严格遵守文档要求来写
// vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
// 选项
})
剩下的就看文档改吧
ref API
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。
有些时候会不可避免的对DOM进行手动操作,使用 ref 可以获取都页面上的某个DOM 元素。而且可以获取到组件,使用 ref 获取到的组件,是组件实例对象,而使用id获取的组件,获取的是组件中的DOM对象
1.在标签中使用ref ='自定义名'
<p ref="p">hello</p>
2.在组件上使用ref
<child-component ref="child"></child-component>
props API
props的值是单向传递的,只能从父组件向子组件进行传递,不能在子组件去修改props属性的值
props的三种写法
数组式
props:['name','age','sex']
对象式可以指定数据类型
props:{
name:String,
age:Number,
sex:String
}
对象式可以指定数据类型和默认值
props:{
name:{
type:String,
default:'默认名字'
}
}
通过传入对象Vue自动结构赋值3
传入一个对象所有的属性
如果你想要将一个对象的所有 property 都作为 prop 传入,你可以使用不带参数的
v-bind (取代v-bind:prop-name)。例如,对于一个给定的对象post:|
post: { id: 1, title: 'My Journey with Vue' }下面的模板:
<blog-post v-bind="post"></blog-post>等价于:
<blog-post v-bind:id="post.id" v-bind:title="post.title" ></blog-post>Prop是单向下行绑定,父级的更新会向下流动到子组件中,prop可以添加验证机制,判断传的值是否是正确的类型
mixin混入
为了提高复用性,使用 mixin 可以使得多个组件使用同一个配置,mixin文件可以配置vc中所有的配置项,像一个另类的类
使用方法 1.首先新建一个js文件 2.在js中写入混入的配置,假设有多个组件需要使用同一个方法,比如弹窗提示你点击了这里 3.导出一个配置项 4.在需要使用mixin文件的组件中导入mixin文件 5.在配置项中使用mixins项进行使用例如 mixins:[mixin]
// mixin.js
export const mixin = {
methods:{
alertInfo(){
alert('你点击了我')
},
}
}
//=============================================================
在组件中使用mixin
//Student.vue组件
<script>
import { mixin } from './mixin.js'
export default {
mixins:[mixin]
<script>
可以在「main.js」文件中,可以进行全局引用mixin,但是要在创建Vue实例之前使用,使用Vue.mixin(mixin对象名)进行全局注册mixin
插件 install
使用插件需要使用一个包含install方法的一个对象,或者直接导出一个install方法,install方法的第一个参数是Vue,第二个以后的参数是插件使用者自己传入的数据
插件常用于开发全局功能
通过全局方法 Vue.use() 使用插件。它需要在你调用 new Vue() 启动应用之前完成:
插件文件
export default {
install(Vue) {
console.log('这是插件');
// 定义全局的过滤器
Vue.filter('mySlice', function (value) {
// 返回 value 的前四位
return value.slice(0, 4);
})
// 定义全局指令
Vue.directive('fbind', {
bind() { }, //绑定时调用
inserted() { }, //插入完成后调用
update() { } //数据所在的模板重新被解析时调用
})
// 定义全局方法,定义在原型对象上
Vue.prototype.$printPl = function () {
alert('这是定义在插件里面的全局方法');
}
}
}
在 main.js 中引入并使用插件
import Vue from 'vue'
import App from './App.vue'
// 引入插件
import Pulgin from './assets/tools/install.js'
Vue.config.productionTip = false;
// 使用插件
Vue.use(Pulgin);
// 使用插件要在创建Vue实例之前
new Vue({
render: h => h(App),
}).$mount('#root')
组件自定义事件
自定义事件适用于 子组件==>父组件 传递数据
Vue的自定义事件是给组件用的,使用this.$emit(‘事件名’,数据)进行触发事件
自定义事件组件交互4
自定义事件组件交互
props是父组件向子组件传递数据,自定义事件可以向父组件进行数据传递,关键词:emit,翻译:发出假如一个表单中的输入数据要传递给父组件的H1标签进行显示,首先对这个表单的submit事件进行监听,回调函数采用自定义函数,自定义函数内这样写:
this.$emit("自定义事件名",this.<数据>),在父组件的子组件引用标签内加入一个事件监听,监听的事件名为字组件中自定义的事件名,回调函数接受,回调函数的第一个参数接受的就是子组件汇总传递过来的数据,在在这个函数中将本地的变量重新赋值,在通过模板语法动态的显示H1标签在子组件的25行,使用了
$emit进行向父组件的传值App.vue <template> <img alt="Vue logo" src="./assets/logo.png"> <h1>{{resdata}}</h1> <MycomponentVue @resData='getResdata'/> </template> <script> import MycomponentVue from './components/Mycomponent.vue'; export default { name: 'App', data(){ return { resdata:'' } }, components: { MycomponentVue }, methods:{ getResdata(data){ this.resdata = data; } } } </script> <style> </style>子组件 <template> <h1>props</h1> <p>{{ title }}</p> <form @submit.prevent="sendMainData"> <input v-model="tdata" type="text"> <p>{{ tdata }}</p> <button>点击我发送数据到主文件的H1</button> </form> </template> <script> export default { name:'conponent1', data(){ return { tdata:'', } }, methods:{ sendMainData(){ this.$emit('resData',this.tdata) } } } </script> <style scoped> </style>
灵活性更强的写法
一般我们就使用上面的写法进行添加事件,但是如果有延时的需求的话,就可以使用生命周期钩子函数配合ref进行定义
App.vue
<Student ref='student'/>//引入组件并建立ref对象
mounted(){
//在渲染完成时做的事情
//通过this.$refs拿到组件的ref对象,并用$on添加事件
//通过这样的方可以添加延时器
setTimeout(function(){
this.$refs.student.$on('事件名',事件触发的方法)
//如果指向触发一次事件,就使用以下代码
this.$refs.student.$once('事件名',事件触发的方法)
},3000)
}
//this的指向问题
在this.$refs.student.$once('事件名',事件触发的方法)中,事件触发的方法可以写为匿名函数,
this.$refs.student.$once('事件名',function(){
console.log(this);//匿名函数中的this指向的是 触发这个事件 的组件实例,而不是父组件,
如果使用了箭头函数,这个代码写在哪,this就指向哪
})
解绑自定义事件
this.$off('事件名'):解绑一个自定义事件
this.$off(['事件名1','事件名2',.....]):解绑多个自定义事件
this.$off():解绑全部的自定义事件
this.$destory():销毁当前组件,在销毁组件的时候会自动解绑组件上所有的自定义事件
给组件使用原生DOM事件
#重要概念-Vue#使用@原生事件.native进行修饰,例如<Student @click.native = 'show' />
全局事件总线#重要概念-Vue#
可以实现任意组件中的数据通信,写法有很多,最标准的写法是利用生命周期
全局事件不是程序员写好的,而是一种依照现有的特性进行了融合,更像是一种设计模式
使用方法:在main.js中创建一个组件,然后把这个组件挂载到Vue.prototype上,因为他是一个组件,所以他可以使用Vue原型上面的$on、$emit、$once等方法,这个组件就相当于一个中转站,我们也可以直接把vm实例当做这个中转站,标准写法就是把vm当做中转
在beforeCreate生命周期函数中写入将自身添加到Vue原型上,一般命名为$bus,生命周期钩子函数中的this就是这个组件的实例
main.js
new Vue({
render: h => h(App),
beforeCreate(){
Vue.prototype.$bus= this;//安装全局事件总线
}
}).$mount('#app')
再结合上面灵活性更强的写法5中提到的this指向问题,使用匿名函数作为事件触发函数时,this指向的是触发事件的组件,而使用箭头函数时,this指向的是当前组件,所以通过箭头函数就能实现任意两个组件之间的数据通信
用完了事件,如果用不到了,不要忘记解绑事件
本地存储
存储
localStorage:使用localStorage.setItem('键','值')进行存储,键值对都是字符串
因为本地存储使用的都是字符串,在传入的时候如果不是字符串类型的会自动调用toString方法,在存储对象的时候,就需要使用JSON.stringify(对象)方法,将对象转化为JSON字符串进行存储
读取
使用localStorage.getItem(键名)进行读取数据,如果读取的是一个对象,那么需要使用JSON.parse()进行解析,解析成对象
删除
使用localStorage.removeItem(键名)进行删除
清空本地存储
使用localStorage.clear()进行清空本地存储
sessionStorage
这种存储方式的API和localStorage的API完全一直,区别在于sessionStorage的存储是临时的
Vue动画和过渡
transition标签在Vue中不会被解析为真实DOM,只是用来提供添加动画的标签
在Vue提供了 <transition> </transition> 进行快捷的添加动画效果,<transition-group> </transition>标签能写多个标签,transition内的标签都要有key属性
要添加动画效果首先要自己写好动画,然后新建两个类,一个是进入、一个退出,如果transition标签没有name属性,那么会找到CSS中的 v-enter-active 和 v-leave-active 样式进行添加,如果transition标签有nama属性, 那么会去找<name>-enter-active 和 <name>-leave-active 样式进行添加
在一开始就进行动画展示:向transition标签添加 appear属性并设置为真,可以简写为 appear,如下
<transition appear>
<h1 v-show="isshow" id="showh1">展示界面</h1>
</transition>
动画效果定义如下
.v-enter-active {
animation: showdonghua 1s linear;
}
.v-leave-active {
animation: showdonghua 1s reverse;
}
@keyframes showdonghua {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0px);
}
}
过渡(懒得写了,自己去看文档吧)
配置代理
跨域:协议、地址、端口号有一个不一致就是跨域
解决方案:1.cors解决,通过后端发送一个文件标识来解决跨域,这是真正意义上的跨域
2.jsonp,用的不多
3.代理服务器(重点)
使用Vue-cli配置
在vue.config.js文件添加以下配置
使用这种方法只能配置一个代理
module.exports = {
devServer: {
//proxy的字符串是需要请求到的服务器
proxy: 'http://localhost:4000'
}
}
更详细的配置方式
这种方式可以写多个
目标:本机是8080端口,需要向5050端口的服务器请求student数据
//组件
axios.get('http://localhost:8080/tag/student')//向代理服务器去请求
.then(response=>{},error=>{});
//vue.config.js文件
module.exports = {
devServer: {
proxy: {
'/tag': {//这个是请求前缀
target: 'http://localhost:5050',//这个是代理转发的目标服务器
pathRewrite:{'^/tag',''},//这个是重写路径,是一个对象,第一个是正则,第二个是匹配后重写为啥
ws: true,
changeOrigin: true//如果为true,代理服务器会以目标服务器的端口进行通信,这里就是5050,默认就是true
},
}
}
}
Vue插槽
默认插槽
使用成对标签显示组件,然后在组件标签中间写入dom,在组件里面写<slot></slot>定义插槽的位置
具名插槽
当使用多个插槽时,需要对插槽进行命名,通过name属性进行命名,在组件标签中的dom添加一个slot属性。通过slot='name'对插槽进行索引
//组件文件
<template>
<div>
<h1>这是插槽</h1>
<slot name="test">哈哈</slot>
</div>
</template>
//App.vue
<Sl>
<h1 slot="test">狠狠的放入</h1>
<h2 slot="test">h2狠狠放入</h2>
</Sl>
//可以为多个DOM指定同一个插槽,也可以使用一个div进行插槽
如果不想使用div包裹进行插槽,可以使用<template>标签进行包裹,
***(template标签不会被解析出真实DOM)* **
并且在<template>标签内添加`slot='name'`或者`v-slot:name`,
**注意!** :`v-slot:name`只能写在<template>标签内