失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Vue框架 ---- 组件高级:ref 动态组件 插槽slot和自定义命令

Vue框架 ---- 组件高级:ref 动态组件 插槽slot和自定义命令

时间:2022-12-25 03:39:01

相关推荐

Vue框架 ---- 组件高级:ref 动态组件 插槽slot和自定义命令

Vue框架

内容管理

ref引用使用ref引用DOM元素使用ref引用组件实例----控制文本框和按钮的按需转换this.$nextTick(cb)将cb延迟到DOM更新完 动态组件keep-alive保持组件状态 插槽slotslot的基本使用没有预留插槽,自定义内容丢弃后备内容【默认内容】--- slot标签域内容 具名插槽具名插槽插入内容 v-slot:名称 【slot已经弃用】具名插槽简写 : #插槽名 作用域插槽解构作用域插槽作用域插槽应用 自定义指令私有自定义指令 directives结点下声明全局自定义指令updated函数保持v-focus持续触发指令的参数值 Table案例

Vue3组件基础:ref引用、动态组件、插槽、自定义指令

前面简单介绍了组件的相关,比如监听,组件关系和组件的数据共享,还有自定义事件,这样一个界面就可以为不同的组件相互作用结合形成,数据传递则依靠指令和之间【后代可以使用provide和inject便捷传输】 复杂的数据传递一般使用vuex

其实很多得概念之前就提到了,比如这里得ref引用;【这个在Spring的IOC的属性注入的位置,对象属性就是ref,普通的属性就是value】,之前的响应式数据传递,就配置全局数据项,就可以不写.value

ref引用

ref引用就是对象的引用,ref是帮助programmer在不依赖JQuery的情况下,获取DOM元素或者组件的引用【之前Jq最方便的就是简化了对象的操作,特别是$(选择器:过滤器)】

Vue里面是不建议使用Jq的 ,因为容易造成引用的混乱,所以就要使用ref来操作DOM或者组件。每一个vue的组件实例上,都包含一个$refs对象,里面存储着对应的DOM元素或者对于组件的引用,默认情况下,其默认指向一个空对象

之前分享组件的基础的时候,就提过this代表的就是当前组件的实例,这里可以看一下其内容

[[Target]]: Objectnum: (...)username: (...)$: (...)$attrs: (...)$data: (...)$el: (...)$emit: (...)$forceUpdate: (...)$nextTick: (...)$options: (...)$parent: (...)$props: (...)$refs: Object$root: (...)$slots: (...)$watch: (...)_: Object

可以看到有很多的内置的对象,这里就有一个$refs

使用ref引用DOM元素

如果想要对页面上的某个DOM元素进行操作,就给需要操作的DOM结点添加ref属性

为对应的DOM添加ref属性,指明引用的名称

<h1 ref="myh1">LifeCircle子组件</h1>

通过this.$refs.引用名称,获取到dom元素的引用

通过该引用操作DOM元素

<button type="button" @click="getDom">获取DOM结点h1</button>methods:{getDom() {console.log(this.$refs.myh1) //因为会将带有ref属性的结点注册到$refs中,所以这里想要使用myh1,就直接.引用即可}}

这里打印的结果就是: < h1>LifeCircle子组件< /h1>;成功获取到了该组件对应页面上的DOM结点,比如这里想要修改文本的颜色: this.$refs.myh1.style.color = 'red’就可以设置红色

使用ref引用组件

如果想要引用页面上的组件【组件对于父组件来说也是一个标签,和上面的DOM一样是一个结点】

为要引用的组件加上ref引用名称使用this.$refs.引用名称就可以获取到组件的实例对象,通过.methods就可以直接使用组件的methods结点中定义的方法

这里比如在consum-kid组件中定义了方法setColor,可以获取组件页面中的dom元素修改其背景颜色,在App中点击按钮达到效果

//consum-kid.vueX * 2 + 1的结果为 :<span ref='myspan' :style="{'background-color':color}">{{count * 2 + 1}}</span>methods:{setColor() { //在子组件中定义了一个set方法,在另一个组件中点击按钮就可以执行该方法,那么就要使用组件的引用this.$refs.myspan.style.backgroundColor = 'pink'}}//父组件App.vue<button type="button" @click="changeColor">改变子组件的字体的颜色</button><cosum-kid ref="conKid"></cosum-kid>methods:{changeColor(){this.$refs.conKid.setColor() //获取子组件调用其set方法修改颜色}}

这样通过ref引用就可以方便操作组件及上面的DOM结点

实例----控制文本框和按钮的按需转换

通过布尔值inputVisible来控制组件中的文本框于按钮的按需切换

当为true的时候就可以展示文本输入框,要想展示的一瞬间获得焦点,就使用元素js的方法.focus()即可;所以通过ref引用获取文本框即可

<hr color="#BA8B00"><input type="text" ref="ipt" v-if="inputVisible" /><button v-else type="button" @click="showInput" class="btn btn-primary">展示input的输入框</button><hr color="#BA8B00" />methods:{showInput() {this.inputVisible = truethis.$refs.ipt.focus()}}

这样点击按钮就可显示文本框,但是控制台报错:Uncaught TypeError: Cannot read properties of undefined (reading ‘focus’) — 也就是浏览器并没有检测到文本框undefined

DOM元素的更新是异步的,也就是异步的任务【因为要重新渲染结点,属于宏任务】,在EventLoop中,这是在一个消息队列中,主任务就是优先执行,所以会立即去执行this.$refs,这个时候并没有获取到结点,报错

this.$nextTick(cb)将cb延迟到DOM更新完

上面就发现因为组件的更新是异步的,而js是将栈中的所有的主任务执行完毕才会执行异步任务,所以调用不应该在主任务,vue提供了内部函数$nextTick(cb),会将回调函数推迟到下一个DOM更新周期之后执行,也就是登组件重新渲染更新完毕之后,才会执行cb函数,保证cb操作的最新的回调函数

methods:{showInput() {this.inputVisible = true//把对dom元素的操作推迟到页面的DOM更新完毕之后执行this.$nextTick(() => {this.$refs.ipt.focus()})}}

这里将执行语句放到匿名回调函数中,等待更新完毕之后执行,相当于也是异步的任务

动态组件

动态组件指的是动态切换组件的显示和隐藏,vue提供了一个内置的< compnent>组件,用来实现组件的动态渲染 【之前的普通的DOM结点的显示可以使用v-if或者v-show】

component是组件的占位符通过js 属性动态指定要渲染的组件的名称< component is=“要渲染的组件的名称”>< /component>

也就是使用component标签占据位置,通过这个标签的is属性就可以动态绑定组件

<template><img alt="Vue logo" src="./assets/logo.png" /><br/><button type="button" @click="changeColor">改变子组件的字体的颜色</button><br><button type="button" @click="showComp">动态显示组件</button><br>姓名<input type="text" v-model.lazy="info.username"/><hr/><!-- <life-circle v-if="flag"></life-circle><cosum-kid ref="conKid"></cosum-kid> --><component :is="conName"></component></template>data() {return {conName:'',showComp() {this.conName = 'LifeCircle'}

这样只要点击按钮,就可以显示LifeCircle组件

keep-alive保持组件状态

这里的component占位的效果,其实也是动态创建或者销毁组件实例,当切换其他的组件的时候,之前的组件实例就被销毁,第二次切换回来的时候就是重新创建组件实例,所以之前的状态就会恢复到最初的状态, 如果想要不销毁,那么就要使用keep-alive

默认情况下,切换动态组件时 无法保持组件的状态,这个时候可以使用vue内置的< keep- alive>组件包裹component标签保持动态组件的状态

<keep-alive><component :is = 'conName'></component></keep-alive>

这样组件实例切换的时候就不会被销毁,组件实例就会被缓存到浏览器的内存中,一般都会使用keep-alive来保持之前页面的状态

插槽slot

插槽是vue为组件的封装er提供的能力,允许programmer在封装组件的时候,把不确定的、希望由用户指定的部分定义为插槽

这样就可以通过插槽将html小的页面插入到封装好的组件中,插槽就是在组件的封装期间,为用户预留的占位符;上面的动态组件的component也是占位符,但是占的是整个组件的位,这里占位站的就只是DOM的位置

slot的基本使用

在封装组件期间,可以通过< slot>元素定义插槽,从而为用户预留的内容进行占位

<template><p>这是子组件的第一个p标签</p><slot></slot> <!-- 插槽:不确定放什么内容,后面组件的使用者进行自定义 --><p>这是子组件的第二个P标签</p></template>

使用者,也就是父组件调用的时候,使用双目的子组件的标签,标签之间内容都会被填充到插槽

这里可以演示一下

<template><p>SlotTest组件 ---- 这是第一个p标签;下面就是使用者自定义的内容</p><slot></slot><p>这是第二个p标签</p></template><script>export default {name: 'SlotTest',}</script><style lang="less" scoped></style>-------------------父组件App.vue进行调用--------------<!-- 调用子组件时,标签之间的内容就会被填充到子组件的插槽中 --><slot-test><div>我是App根组件自定义的内容</div></slot-test>

没有预留插槽,自定义内容丢弃

就是如果在组件中没有定义slot插槽,那么就算在父组件使用时,在标签间定义了内容,也不会填充,因为没有插槽,那么效果就是会被自动舍弃

后备内容【默认内容】— slot标签域内容

封装组件时,可以为预留的slot 插槽提供后备内容【默认内容】,如果使用者没有为插槽提供内容,那么就会使用后备内容,提供了就会覆盖

<template><p>第一个p标签</p><slot>插槽的后备内容都在这里 【 如果使用者不提供,改内容生效】 --- 这样也实现动态页面</slot><p>第二个p标签</p></template>

具名插槽

上面的只是定义了一个插槽,插槽标签slot中的内容就是后备内容;如果需要在封装组件的时候预留多个插槽结点,则需要为每一个插槽指定具体的name名称,这种含有名称的插槽为具名插槽

<template><header><!-- 页面的标题 --><slot name="header">后备内容</slot></header><main><slot>这是一个默认的插槽</slot></main><footer><slot name="footer">后备内容 --- 具名插槽</slot></footer></template><script>export default {name: 'SlotTest',}</script><style lang="less" scoped></style>

如果没有指定name名称的插槽,那么这个插槽的名称为default— 所以只能由一个default

具名插槽插入内容 v-slot:名称 【slot已经弃用】

比如这里定义了3个插槽

<template><div><header><!-- 页面的标题 --><slot name="header">后备内容 ---- header</slot></header><slot>默认的插槽</slot><footer><slot name="footer">后备内容 --- 具名插槽</slot></footer></div></template>

在App根组件中要使用这个组件,传入了需要插入的自定义的内容

<slot-test><div><h3>春晓</h3><center>孟浩然</center><p>春眠不觉晓,处处闻啼鸟</p><p>夜来风雨声,花落知多少</p></div></slot-test>

最终渲染的结果就是: 所有的内容都进入了默认插槽;也就是说,在不特殊说明的情况下,插入的内容都会进入默认插槽

要让内容进入具名插槽,需要使用template标签包裹内容,并且使用v-slot指定剧名插槽的名称

<!-- 调用子组件时,标签之间的内容就会被填充到子组件的插槽中 --><slot-test><template v-slot:header><h3>春晓</h3></template><template v-slot:default><center>孟浩然</center></template><template v-slot:footer><p>春眠不觉晓,处处闻啼鸟</p><p>夜来风雨声,花落知多少</p></template></slot-test>

对要插入的内容使用template标签包裹,并且使用v-slot指明具名插槽的名称,使用: ,不是=号,并且直接写名称,不用加引号,不然会报错

Error: Codegen node is missing for element/if/for node. Apply appropriate transforms first.

这里的问题就是因为:template标签放的位置有问题,template必须是最外层的标签,外面不能包裹div了,报错就是因为组件标签里的内容包裹在div中:happy:,template应该是最外面 ----- div也是属于DOM结点,template才能将其渲染到界面上 ---- 所以template必须包裹所有的DOM

<slot-test><template v-slot:header><h3>春晓</h3></template><span style="align-content: center;">作者:孟浩然</span><template v-slot:footer><p>春眠不觉晓,处处闻啼鸟</p><p>夜来风雨声,花落知多少</p></template></slot-test></template>

默认插槽可以省略template,具名插槽不能省略

具名插槽简写 : #插槽名

和v-on和v-bind一样,v-slot也可以简写,把参数之前的内容v-slot:替换为字符#, 比如

<template v-slot:footer><template #footer>

这里可以修改上面的代码

<slot-test><template #header><h3>春晓</h3></template><template #default><span style="align-content: center;">作者:孟浩然</span></template><template #footer><p>春眠不觉晓,处处闻啼鸟</p><p>夜来风雨声,花落知多少</p></template>

作用域插槽

之前的作用域插槽slot-scope已经弃用,在封装组件的过程中,可以为预留的slot插槽绑定props数据,带有props数据的slot就是作用域插槽

也就是说插槽中有数据,就是为slot动态绑定数据

<slot :prop = 'XXX'></slot>

使用者使用的时候传入数据的时候,还可以指定prop绑定的数据

<template #default='scope'>xxx</template>

在插槽的名称后面通过=‘scope’ ;然后这个scope就可以接收到上面的属性prop, 也就是实现了子组件的数据传输到了父组件

<slot name="header" :info = 'infomation' :msg = 'message'>data() {return {infomation:{stuname: 'Cfeng',stuClass: 'HC2001',stuMajor: 'CS'},message: 'Hello,Cfeng!!'}}--------------------------------------------------------------<slot-test><template #header='scope'><p>{{scope}}</p></template></slot-test>

然后打印的结果就是: { “info”: { “stuname”: “Cfeng”, “stuClass”: “HC2001”, “stuMajor”: “CS” }, “msg”: “Hello,Cfeng!!” }】

也就是scope会接收插槽传递的所有的属性形成的JSON对象

解构作用域插槽

之前已经使用过很多次解构了,就是可以直接加上{},然后就可以直接取出对象中的属性;

<template #header='{msg,info}'>

这样就可以直接使用msg的值,而不再需要使用scope.msg来获得数据

作用域插槽应用

作用域插槽的最主要的特点就是组件的多态,就类似之前的java的abstract一样;不会具体定义,交给用户来决定数据的样式

比如这里子组件提供了一个table

<template><div><table style="border: 1px solid rosybrown;"><th><td>序号</td><td>姓名</td><td>状态</td></th><tr v-for="item in list":key="item.id"><td>{{item.id}}</td><td>{{item.name}}</td><td>{{item.state}}</td></tr></table></div></template><script>export default {name: 'SlotTest',data() {return {list:[{id:1,name:'张三',state:true},{id:2,name:'李四',state:true},{id:3,name:'Cfeng',state:true}]}}}</script>

这里的子组件将数据直接给到了template中,但是问题就是这里的state,并不知道用户想要一个什么样子的样式,是复选框,还是什么;所以这里不要直接将数据按照特定的格式渲染,而是交给使用者App来按需操作

<template><div><table style="border: 1px solid rosybrown;"><th><td>序号</td><td>姓名</td><td>状态</td></th><tr v-for="item in list":key="item.id"><slot :item = 'item'><!-- 插槽中放一个默认的渲染的样式,用户如果忘记可以后备 --><td>{{item.id}}</td><td>{{item.name}}</td><td>{{item.state}}</td></slot></tr></table></div></template>

在App.vue中通过作用域插槽的操作,来进行具体的渲染

<slot-test><template #default='{item}'><td>{{item.id + 1}}</td><td>{{item.name}}</td><td><input type="checkbox" :checked="item.state" /></td></template></slot-test>

父组件就可以解构出item属性然后使用,自定义样式;比如这里将state渲染成了一个复选框的样式

⚠: Whitespace was expected. 这是因为v-for指令和:key两个属性之间需要空格

<tr v-for = 'item in list' :key='item.id'> //因为这是属性绑定,key不是修饰符,绑定的key属性,两个不同的指令或者属性之间要有空格

自定义指令

vue官方提供了v-for,v-bind等内置指令,除此之外vue还允许开发者自定义指令,vue自定义指令主要有两类:

私有自定义指令全局自定义指令

私有自定义指令 directives结点下声明

这里先定义一个组件MyHome,其中有一个文本框,现在的需求: 当渲染出组件的时候,文本框自动获得焦点

可以使用之前的ref来动态获得组件【这里使用的是动态显示组件,点击按钮会显示MyHome组件,然后这里的渲染必须是异步任务,所以需要使用$nextTick,这里前面是获取组件,后面是获取组件上的结点

<input ref="ipt" type="text" class="form-control" /><keep-alive><component :is="conName" ref="myHome"></component></keep-alive>showComp() {this.conName = 'MyHome'this.$nextTick(() => {//变成异步任务this.$refs.myHome.$refs.ipt.focus()})}

这里直接给动态组件加上了ref属性,也是可以获取到这里具体的组件的

这里可以使用自定义指令,比如为input绑定自定义指令v-focus

<input type="text" class="form-control" v-focus/>

[Vue warn]: Failed to resolve directive: focus --自定义指令必须要进行声明

使用自定义指令,必须以v-开头,但是在directives下面声明私有指令时,不用v-这里的directives结点和data等结点平级

directives: {//自定义一个私有指令focus: {//当绑定元素插入到DOM时,自动会触发mounted函数mounted(e1) {e1.focus()}}}

这里mounted的参数就是自定义指令绑定的DOM结点;mounted函数的执行时机: 指令绑定的结点渲染到DOM结构的时候自动触发

<input type="text" class="form-control" v-focus />directives:{focus: {mounted(e) {e.focus()}}}

自动执行mounted方法,获取焦点; 所以自定义的私有指令就是在对应的组件的directives结点中声明指令,然后就可以调用了,mounted函数可以获取到绑定的元素DOM

全局自定义指令

上面的v-focus指令声明在MyHome组件中,在其他的组件中是不能使用这个指令的;就类似之前的组件的全局注册一样;只要在main.js进行指令声明就可以使用,使用spa_app.directive方法可以声明,第一个是名称,第二个是指令的方法体

import {createApp } from 'vue'import App from './App.vue'import './index.css'import './assets/css/bootstrap.css'//导入axiosimport axios from 'axios'const spa_app = createApp(App)//在mount之前进行配置//声明请求的相对路径axios.defaults.baseURL = '/api'//全局注册挂载spa_app.config.globalProperties.$ajax = axiosspa_app.config.unwrapInjectedRef = truespa_app.directive('focus',{mounted(e) {e.focus()}})spa_app.mount('#app')

还是要在spa_appmout之前进行声明,和组件的全局注册类似

全局声明自定义指令之后,不管在哪个组件中都可以使用该指令,这里将私有的v-focus声明去除;在MyHome组件中还是可以使用

updated函数保持v-focus持续触发

上面的v-focus指令有点缺陷: —mounted函数只是在元素第一次插入DOM时被调用,当DOM更新时mounted函数不会被触发; 与之相比,updated函数【之前分享组件的生命周期的时候,组件的几个函数和DOM的函数相同,mounted就是渲染到页面后触发,而updated就是每次页面更新都会触发】

spa_app.directive('focus',{mounted(e) {e.focus()},updated(e) {e.focus()}})

这样声明之后就可以渲染和更新的时候都会获取焦点【和组件的生命周期函数是相同的】组件也可以看作父组件的一个DOM结点

<template><div class="home-container"><p>MyHome组件 ---- {{count}}</p><hr color="yellowgreen"/><input ref="ipt" type="text" class="form-control" v-focus /><br><button type="button" class="btn btn-primary" @click="count++">数值+ 1</button></div></template>

这里点击按钮页面更新,这个时候会执行updated函数,还是会获取焦点

在vue2项目中使用自定义指令,是没有ed的,就是mount和update【提一句】

函数简写

如果mounted函数和updated函数的逻辑完全相同,就可以将方法的第二项完全变成一个方法,而不是方法体

spa_app.directive('focus',(e) => {e.focus()})

指令的参数值

自定义指令声明的方法的第一个形参指代的DOM对象,第二个形参指定的时指令绑定的参数对象,通过.value获取参数对象的具体值

vue提供的指令都是支持参数的,自定义指令也是支持的,在绑定指令的时候,可以通过等号的形式为指令绑定具体的参数值

<input type='text' v-model.number = 'count' v-focus v-color= "'red'" />

比如上面就为v-color自定义指令绑定了参数red;

声明指令的时候,可以通过函数的形参binding来接收绑定的参数,第一个参数是指代的DOM对象,第二个参数就是binding参数; 注意binding接收的是一个对象,获取red要使用binding.value

spa_app.directive('color', (e,binding) => {e.style.backgroundColor = binding.value})

子组件使用v-color指令时,需要注意里面还有单引号; 因为如果时属性绑定,后面的变量就要包裹在引号中,现在这个变量时字符串,所以需要有两重的引号

Table案例

案例达到的效果就是商品列表,主要步骤

首先建立一个vite项目table-demo,初始化项目

npm init vite-app table-democd table-demonpm inpm i less -Dnpm i axios -Snpm run dev

同时要导入bootstap.css,修改index.css全局的样式

:root {font-size: 12px;}body {padding: 8px;}

请求商品列表的数据 ---- 上面安装了axios包,接下来就是在mian.js中进行配置

methods:{async getGoodsList() {const {data: res} = await this.$ajax.get('/goods')if(res.status !== 0) return console.log("请求商品列表失败")this.goodsList = res.data} },components: {},created() {this.getGoodsList()}}

这里需要注意的就是定义的全局属性$ajax要通过this进行调用,不能直接写出,不然undefined

封装MyTable组件

封装的要求: 用户通过名为data的prop属性,为MyTable组件指定数据源; 在Mytable组件中,预留名称为header的具名插槽;同时要预留名为body的作用域插槽

这里模板结构还是基于的bootstrap进行渲染,这里的作用域插槽携带的数据就是row当前的数据对象和当前的索引index

<template><!-- <button type="button" class="btn btn-primary">jkj</button> --><my-table :data = 'goodsList'><template #header><tr><th>#</th><th>商品名称</th><th>价格</th><th>标签</th><th>操作</th></tr></template><template #body="{row,index}"><td>{{index + 1}}</td><td>{{row.goods_name}}</td><td>¥{{row.goods_price}}</td><td>{{row.tags}}</td><td><button type="button" class="btn btn-danger btn-sm">删除</button></td></template></my-table></template><script>import MyTable from './components/my-table/MyTable.vue'export default {name: 'App',data() {return {goodsList:[],}},methods:{async getGoodsList() {const {data: res} = await this.$ajax.get('/goods')if(res.status !== 0) return console.log("请求商品列表失败")this.goodsList = res.data} },components: {MyTable,},created() {this.getGoodsList()}}</script><style lang="less" scoped></style>

实现删除的功能

为按钮添加事件处理函数,根据id删除goodsList中的数据

<button type="button" class="btn btn-danger btn-sm" @click="onRemoveGoods(row.id)">删除</button>onRemoveGoods(id) {this.goodsList = this.goodsList.filter(x => x.id !== id) //过滤出不是id的所有的数据}

实现添加标签的功能

<td><!-- 循环渲染标签 --><span class="badge badge-warning ml-2" v-for="tag in row.tags">{{tag}}</span></td>

标签tags也是一个数组,所以需要使用class进行渲染

文本输入框的焦点事件blur,就是失去焦点的时候就会触发

这里的所有的代码都是在App.vue完成的

<template><!-- <button type="button" class="btn btn-primary">jkj</button> --><my-table :data = 'goodsList'><template #header><tr><th>#</th><th>商品名称</th><th>价格</th><th>标签</th><th>操作</th></tr></template><template #body="{row,index}"><td>{{index + 1}}</td><td>{{row.goods_name}}</td><td>¥{{row.goods_price}}</td><td><!-- 基于当前的inputVisible,来控制input和button的按需显示 --><input type="text" class="form-control form-control-sm ipt-tag" v-if="row.inputVisible" v-focus v-model.trim = 'row.inputValue' @blur="onInputConfirm(row)" @keyup.enter="onInputConfirm(row)" @keyup.esc = "row.inputValue =''"/><button type="button" class="btn btn-primary btn-sm" v-else @click="row.inputVisible = true">+Tag</button><!-- 循环渲染标签 --><span class="badge badge-warning ml-2" v-for="tag in row.tags">{{tag}}</span></td><td><button type="button" class="btn btn-danger btn-sm" @click="onRemoveGoods(row.id)">删除</button></td></template></my-table></template><script>import MyTable from './components/my-table/MyTable.vue'export default {name: 'App',data() {return {goodsList:[],}},methods:{async getGoodsList() {const {data: res} = await this.$ajax.get('/goods')if(res.status !== 0) return console.log("请求商品列表失败")this.goodsList = res.data},onRemoveGoods(id) {this.goodsList = this.goodsList.filter(x => x.id !== id) //过滤出不是id的所有的数据},onInputConfirm(goods) {//因为双向绑定,所以输入的值在inputValue中const val = goods.inputValuegoods.inputValue = ''//隐藏文本框goods.inputVisible = false//判断重复和空if(!val || goods.tags.indexOf(val) !== -1) return//将内容存放到tags中goods.tags.push(val)}},components: {MyTable,},created() {this.getGoodsList()}}</script><style lang="less" scoped>.ipt-tag {width: 80px ;display: inline;}</style>

这样就完成了列表的标签的添加

vue中关于组件部分就介绍到这里,接下来就是路由了🎉

如果觉得《Vue框架 ---- 组件高级:ref 动态组件 插槽slot和自定义命令》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。