Vue [Day4]

news2025/1/19 14:14:33

组件的三大组成部分

在这里插入图片描述

组件的样式冲突 scoped

在这里插入图片描述

<style scoped>

</style>

data 是一个函数

在这里插入图片描述
components/BaseButton.vue

<template>
    <div class="BaseButton">
        <button @click="count--">-</button>
        <span>{{ count }}</span>
        <button @click="count++">+</button>
    </div>
</template>

<script>
export default {
    // data必须写成函数,不能是对象
    data() {
        return {
            count: 999
        }
    }
}
</script>

<style>
</style>


App.vue

<template>
    <div id="app">
        <BaseButton></BaseButton>
        <BaseButton></BaseButton>
        <BaseButton></BaseButton>
    </div>
</template>

<script>
import BaseButton from './components/BaseButton.vue'

export default {
    name: 'App',
    components: {
        BaseButton
    }
}
</script>

<style>
</style>

组件通信

在这里插入图片描述


在这里插入图片描述



父 -> 子 props

在这里插入图片描述
components/SonTest.vue

<template>
    <div class="son">
        {{ title }}
        <!-- 渲染使用 -->
    </div>
</template>

<script>
export default {
    // 2.通过props进行接受
    // 这里的名字必须和App.vue里的<Son :title="MyTitle"></Son> 相同
    props: ['title']
}
</script>

<style  scoped>
div {
    border: 1px solid black;
    width: 100px;
    height: 100px;
}
</style>


App.vue

<template>
    <div id="app">
        我是爸爸
        <!-- 1.给组件标签,添加属性的方式,传值 -->
        <SonTest :title="MyTitle"></SonTest>
    </div>
</template>

<script>
import SonTest from './components/SonTest.vue'

export default {
    components: {
        SonTest
    },
    data() {
        return {
            MyTitle: 'slxhhhh'
        }
    }
}
</script>

<style  >
div {
    border: 1px solid black;
    width: 300px;
    height: 200px;
}
</style>



prop概念

在这里插入图片描述components/UserInfo.vue

<template>
    <div class="UserInfo">
        <h1>个人信息</h1>
        <h3>姓名{{ username }}</h3>
        <h3>年龄{{ age }}</h3>
        <h3>是否单身{{ isSingle }}</h3>
        <h3>座驾{{ car.brand }}</h3>
        <h3>兴趣爱好{{ hobby.join('、') }}</h3>
    </div>
</template>

<script>
export default {
    props: ['username', 'age', 'isSingle', 'car', 'hobby']
}
</script>

<style>
</style>

App.vue

<template>
    <div id="app">
        <UserInfo
            :username="username"
            :age="age"
            :isSingle="isSingle"
            :car="car"
            :hobby="hobby"
        ></UserInfo>
    </div>
</template>

<script>
import UserInfo from './components/UserInfo.vue'

export default {
    components: {
        UserInfo
    },
    data() {
        return {
            username: 'slx',
            age: 20,
            isSingle: true,
            car: {
                brand: 'affrf'
            },
            hobby: ['aaaa', 'cccc', 'bbbb']
        }
    }
}
</script>

<style  >
div {
    border: 1px solid black;
    width: 300px;
    height: 400px;
}
</style>





props校验

类型校验 基础写法+完整写法

在这里插入图片描述
components/BaseProgress.vue

<template>
    <div class="BaseProgress">
        <div class="progress">
            <!-- 在这里面width  不用加{{}}    并且{}里面 是js对象  ,所以要遵守驼峰命名法 也就是 background-color 要变成 backgroundColor-->
            <div
                class="inner"
                :class="{
                    low: w < 50,
                    high: w > 70,
                    over: w == 100
                }"
                :style="{ width: w + '%' }"
            >
                <span>{{ w }}%</span>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    // 没有校验
    // props: ['w']

    // 1.基础校验
    // props: {
    //     // 校验的属性名:类型  Number、String Boolean
    //     w: Number
    // }

    // 2.完整写法(类型、非空、默认、自定义校验
    props: {
        w: {
            // 写成对象形式
            type: Number,
            // required: true,
            default: 10,
            validator(value) {
                // return false
                console.log(value)

                if (value >= 0 && value <= 100) {
                    return true
                }
                console.log('传入的值要是0~100')
                return false
            }
        }
    }
}
</script>

<style scoped>
.BaseProgress {
    margin: 10px;
}

.progress {
    width: 300px;
    height: 40px;
    margin-bottom: 40px;
    background-color: #cdf92c;
    border-radius: 25px;
    padding: 5px;
}

.inner {
    background-color: #0df6c7;
    border-radius: 25px;
    height: 35px;
    margin-top: 3px;
    /* width: 20%; */
}

.low {
    background-color: #92ee61;
}

.high {
    background-color: rgb(141, 179, 216);
}

.over {
    background-color: rgb(0, 128, 255);
}

.inner span {
    width: 100%;
    text-align: right;
    display: block;
    line-height: 90px;
}
</style>

App.vue
<template>
    <div id="app">
        <!-- 没传值,就用默认的10 -->
        <BaseProgress></BaseProgress>

        <BaseProgress :w="width"></BaseProgress>
    </div>
</template>

<script>
import BaseProgress from './components/BaseProgress.vue'

export default {
    components: {
        BaseProgress
    },
    data() {
        return {
            // width: 'sfsd'
            width: 20
        }
    }
}
</script>

<style  >
</style>

prop & data 、单向数据流

在这里插入图片描述components/BaseProgress.vue

<template>
    <div class="BaseProgress">
        <div class="progress">
            <!-- 在这里面width  不用加{{}}    并且{}里面 是js对象  ,所以要遵守驼峰命名法 也就是 background-color 要变成 backgroundColor-->
            <div
                class="inner"
                :class="{
                    low: w < 50,
                    high: w > 70,
                    over: w == 100
                }"
                :style="{ width: w + '%' }"
            >
                <span>{{ w }}%</span>
            </div>
        </div>

        <button @click="handleFn(75)">设置75%</button>
        <button @click="handleFn(100)">设置100%</button>
        <!-- props传过来的数据(外部数据),不能直接改 -->
    </div>
</template>

<script>
export default {
    props: {
        w: {
            // 写成对象形式
            type: Number,
            // required: true,
            default: 10,
            validator(value) {
                if (value >= 0 && value <= 100) {
                    return true
                }
                console.log('传入的值要是0~100')
                return false
            }
        }
    },
    methods: {
        handleFn(tt) {
            this.$emit('changeWidth', tt)
        }
    }
    // 父组件的props更新,会单向向下流动,影响到子组件
}
</script>

<style scoped>
.BaseProgress {
    margin: 10px;
}

.progress {
    width: 300px;
    height: 40px;
    margin-bottom: 40px;
    background-color: #cdf92c;
    border-radius: 25px;
    padding: 5px;
}

.inner {
    background-color: #0df6c7;
    border-radius: 25px;
    height: 35px;
    margin-top: 3px;

    /* width: 20%; */
}

.low {
    background-color: #92ee61;
}

.high {
    background-color: rgb(141, 179, 216);
}

.over {
    background-color: rgb(0, 128, 255);
}

.inner span {
    width: 100%;
    text-align: right;
    display: block;
    line-height: 90px;
}
</style>


App.vue

<template>
    <div id="app">
        <!-- 没传值,就用默认的10 -->
        <!-- <BaseProgress></BaseProgress> -->

        <BaseProgress :w="width" @changeWidth="changeFn"></BaseProgress>
    </div>
</template>

<script>
import BaseProgress from './components/BaseProgress.vue'

export default {
    components: {
        BaseProgress
    },
    data() {
        return {
            // width: 'sfsd'
            width: 20
        }
    },
    methods: {
        changeFn(tt) {
            this.width = tt
        }
    }
}
</script>

<style  >
</style>






子 -> 父 $emit

在这里插入图片描述
components/Son.vue

<template>
  <div class="son" style="border: 3px solid #000; margin: 10px">
    我是Son组件 {{ title }}
    <button @click="changeFn">修改title</button>
  </div>
</template>

<script>
export default {
  name: 'Son-Child',
  props: ['title'],
  methods: {
    changeFn() {
      // 通过this.$emit() 向父组件发送通知
      this.$emit('changTitle','传智教育')
    },
  },
}
</script>

<style>
</style>

App.vue


<template>
  <div class="app" style="border: 3px solid #000; margin: 10px">
    我是APP组件
    <!-- 2.父组件对子组件的消息进行监听 -->
    <Son :title="myTitle" @changTitle="handleChange"></Son>
  </div>
</template>

<script>
import Son from './components/Son.vue'
export default {
  name: 'App',
  data() {
    return {
      myTitle: '学前端,就来黑马程序员',
    }
  },
  components: {
    Son,
  },
  methods: {
    // 3.提供处理函数,提供逻辑
    handleChange(newTitle) {
      this.myTitle = newTitle
    },
  },
}
</script>

<style>
</style>

总结

在这里插入图片描述



【综合案例】——小黑记事本— 组件版

在这里插入图片描述

components/TodoHeader.vue

<template>
    <div class="head">
        <h1>小黑记事本</h1>
        <input
            @keyup.enter="handleAdd"
            v-model="todoName"
            type="text"
            placeholder="请输入待办事项"
        />
        <button @click="handleAdd">添加任务</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            todoName: ''
        }
    },
    methods: {
        handleAdd() {
            if (this.todoName.trim() == '') {
                // 输入许多的空格,无效输入,不让添加
                alert('请输入内容')
                return
            }

            this.$emit('add', this.todoName)

            // 点击添加之后,输入框清空
            this.todoName = ''
        }
    }
}
</script>

<style>
.head {
    width: 243px;
    /* background-color: #584949; */
}

input {
    height: 30px;
    vertical-align: middle;
}

.head button {
    height: 30px;
}
</style>


components/TodoMain.vue

<template>
    <section class="body">
        <ul>
            <li v-for="(item, index) in todoList" :key="item.id">
                <span>{{ index + 1 }}</span>
                <span class="content">{{ item.name }}</span>
                <button @click="handleDel(item.id)">×</button>
            </li>
        </ul>
    </section>
</template>

<script>
export default {
    props: {
        todoList: Array
    },
    methods: {
        handleDel(tt) {
            this.$emit('del', tt)
        }
    }
}
</script>

<style>
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    list-style: none;
}
.body li {
    width: 234px;
    height: 50px;
    display: flex;
    line-height: 50px;
    /* justify-content: space-between; */
    background-color: #de8282;
    border-bottom: black solid 2px;
}

.body li .content {
    flex: 1;
}

.body li button {
    height: 50%;
    align-self: center;
    display: none;
}

.body li:hover button {
    display: block;
    width: 20px;
}
</style>


components/TodoFooter.vue

<template>
    <div v-show="todoList.length > 0" class="footer">
        <span
            >合计:<strong>{{ todoList.length }}</strong></span
        >
        <button @click="clear()">清空任务</button>
    </div>
</template>

<script>
export default {
    props: {
        todoList: Array
    },
    methods: {
        clear() {
            this.$emit('clear')
        }
    }
}
</script>

<style>
.footer {
    width: 234px;
    display: flex;
    justify-content: space-between;
}
</style>


components/App.vue

<template>
    <div id="app">
        <TodoHeader @add="handleAdd"></TodoHeader>
        <TodoMain :todoList="todoList" @del="handleDel"></TodoMain>
        <TodoFooter @clear="handleClear" :todoList="todoList"></TodoFooter>
    </div>
</template>

<script>
import TodoHeader from './components/TodoHeader.vue'
import TodoMain from './components/TodoMain.vue'
import TodoFooter from './components/TodoFooter.vue'
export default {
    components: {
        TodoHeader,
        TodoMain,
        TodoFooter
    },

    // 渲染功能:
    // 1.提供数据:写在公共的父组件 App.vue
    // 2.通过父组件,将数据传递给TodoMain
    // 3.利用v-for 渲染

    // 添加功能
    // 1.收集表单数据 v-model
    // 2.监听事件(回车+点击 都要添加
    // 3.子传父 将任务名称传给父App.vue
    // 4.进行添加 unshift(自己的数据,自己负责)

    // 删除功能
    // 1.监听事件(删除的点击) 携带id
    // 2.子传父,将删除的id传给父组件App.vue
    // 3.父组件删除 filter(自己的数据,自己负责)

    // 底部合计:父传子list  渲染
    // 清空功能:子传父,通知到父组件 父组件清空
    // 持久化存储:watch深度监视->  往本地存 -> 进入页面优先读取本地
    data() {
        return {
            todoList: JSON.parse(localStorage.getItem('list')) || [
                { id: 1, name: '吃水果' },
                { id: 2, name: '喝酸奶' }
            ]
        }
    },
    methods: {
        handleAdd(todoName) {
            this.todoList.unshift({
                id: +new Date(),
                name: todoName
            })
        },
        handleDel(tt) {
            this.todoList = this.todoList.filter((item) => item.id != tt)
        },
        handleClear() {
            this.todoList = []
        }
    },
    watch: {
        todoList: {
            deep: true,
            handler(newValue) {
                localStorage.setItem('list', JSON.stringify(newValue))
            }
        }
    }
}
</script>

<style  >
#app {
    /* width: 234px;
    height: 200px;
    display: flex;
    flex-direction: column; */

    margin: 50px 50px;
}
</style>





非父子通信 event bus事件总线

在这里插入图片描述components/BaseA.vue

<template>
    <div class="A">
        我是A组件(接收方)
        <p>{{ msg }}</p>
    </div>
</template>

<script>
import Bus from '../utils/EventBus'
export default {
    created() {
        // 2.在A组件(接受方)监听Bus的事件(订阅消息)
        // 事件名,回调
        Bus.$on('sendMsg', (msg) => {
            console.log(msg)
            this.msg = msg
        })
    },
    data() {
        return {
            msg: ''
        }
    }
}
</script>

<style>
.A {
    width: 200px;
    height: 100px;
    border: 1px solid black;
}
</style>


components/BaseB.vue

<template>
    <div class="B">
        我是B组件(发布方)
        <button @click="clickSend">发布通知</button>
    </div>
</template>

<script>
import Bus from '../utils/EventBus'
export default {
    methods: {
        clickSend() {
            // 3.B组件(发送方)触发事件的方式传递参数(发布消息)
            Bus.$emit('sendMsg', '恐龙扛狼') // Bus.$on('sendMsg', (msg) => {})和这里的名字同名
        }
    }
}
</script>

<style>
.B {
    width: 200px;
    height: 100px;
    border: 1px solid black;
}
</style>


App.vue

<template>
    <div id="app">
        <BaseA></BaseA>
        <BaseB></BaseB>
    </div>
</template>

<script>


import BaseA from './components/BaseA.vue'
import BaseB from './components/BaseB.vue'
export default {
    components: {
        BaseA,
        BaseB
    }
}
</script>

<style>
</style>


utils/EventBus.js
utils通常用来放工具

// 创建一个都能访问到的事件总线(空的Vue实例)
import Vue from 'vue'

const Bus = new Vue()

export default Bus


非父子通信——provide & inject(扩展)

在这里插入图片描述


v-model原理

¥evevnt也就是e$evevnt也就是e
如果应用于复选框,就是check属性,和change事件的合写

表单类组件封装

e.target.value

在这里插入图片描述components/BaseSelect.vue

<template>
    <div class="BaseSelect">
        <!-- <select v-model="cityId">
        这样写是不行的,因为父组件的数据,只能父组件改,
        而v-model是双向的,他在尝试更改父亲的数据,他要造反,要谋权篡位,所以报错了  
        -->

        <!-- 
            :value="cityId"   用来父传子
        @change="handleChange" 用来子传父
        -->
        <select :value="cityId" @change="handleChange">
            <option value="101">北京</option>
            <option value="102">深圳</option>
            <option value="103">上海</option>
            <option value="104">广州</option>
            <option value="105">辽宁</option>
            <option value="106">福建</option>
        </select>
    </div>
</template>

<script>
export default {
    props: {
        cityId: String
    },
    methods: {
        handleChange(e) {
            console.log(e.target.value)
            this.$emit('changeId', e.target.value)
        }
    }
}
</script>

<style>
</style>



App.vue

<<template>
    <!-- :cityId="selectId"  用来父传子
       @changeId="selectId = $event"   用来子传父
    
    -->
    <BaseSelect :cityId="selectId" @changeId="selectId = $event"></BaseSelect>
</template>

<script>
import BaseSelect from './components/BaseSelect.vue'
export default {
    components: {
        BaseSelect
    },
    data() {
        return {
            selectId: '106'
        }
    }
}
</script>

<style>
</style>



@changeId="selectId = $event " 中的$event是什么

在Vue中,$event是一个特殊的变量,用于在事件处理函数中访问触发事件时传递的数据。它代表了事件对象,包含了与事件相关的信息。

在你提供的代码中,@changeId="selectId = $event"表示当 BaseSelect 组件触发 changeId 事件时,将事件对象中的数据赋值给 selectId。

具体来说,$event 是一个占位符,用于接收传递给事件处理函数的参数。在这个例子中,BaseSelect 组件在触发 changeId 事件时,会将选中的城市ID作为参数传递给事件处理函数。然后,通过 $event 来访问这个参数,并将其赋值给 selectId。

例如,如果 BaseSelect 组件在触发 changeId 事件时传递了一个值为 123 的参数,那么 selectId 将被赋值为 123。代码示例中的 @changeId=“selectId = $event” 就是将事件对象中的数据赋值给 selectId 的方式。

请注意,$event 只是一个约定俗成的命名,你也可以使用其他变量名来接收事件对象中的数据。例如,你可以使用 @changeId=“selectId = value”,其中 value 是你自己定义的变量名,它将接收事件对象中的数据。

总之,$event 是Vue中的一个特殊变量,用于在事件处理函数中访问事件对象中传递的数据。它可以帮助你在事件处理函数中获取和处理事件的相关信息。

v-model 简化代码

在这里插入图片描述components/BaseSelect.vue

<template>
    <div class="BaseSelect">
        <!-- :value="value"  父传子 -->
        <select :value="value" @change="handleChange">
            <option value="101">北京</option>
            <option value="102">深圳</option>
            <option value="103">上海</option>
            <option value="104">广州</option>
            <option value="105">辽宁</option>
            <option value="106">福建</option>
        </select>
    </div>
</template>

<script>
export default {
    // 父传子
    props: {
        value: String
    },
    methods: {
        // 子传父
        // 监听
        handleChange(e) {
            console.log(e.target.value)
            this.$emit('input', e.target.value)
        }
    }
}
</script>

<style>
</style>


App.vue

<template>
    <!-- v-model => :value(父传子)  + @input  子传父 -->
    <BaseSelect v-model="selectId"></BaseSelect>
</template>

<script>
import BaseSelect from './components/BaseSelect.vue'
export default {
    components: {
        BaseSelect
    },
    data() {
        return {
            selectId: '106'
        }
    }
}
</script>

<style>
</style>


小结

在这里插入图片描述


封装输入框组件

在这里插入图片描述


在这里插入图片描述



components/BaseInput.vue

<template>
    <div class="BaseInput">
        <input @change="handleChange" :value="value" type="text" />
    </div>
</template>

<script>
export default {
    props: {
        value: String
    },
    methods: {
        handleChange(e) {
            console.log(e.target.value)

            this.$emit('input', e.target.value)
        }
    }
}
</script>

<style>
</style>


App.vue

<template>
    <div class="app">
        <BaseInput v-model="text"></BaseInput>
    </div>
</template>

<script>
import BaseInput from './components/BaseInput.vue'
export default {
    components: {
        BaseInput
    },
    data() {
        return {
            text: 'slx'
        }
    }
}
</script>

<style>
</style>



.sync修饰符

在这里插入图片描述在书写上比较比v-model麻烦,所以,封装表单还是v-model,其余的用.sync较好


components/SB.vue

<template>
    <div v-show="visable" class="base-dialog-wrap">
        <div class="base-dialog">
            <div class="title">
                <h3>温馨提示:</h3>
                <button @click="close" class="close">x</button>
            </div>
            <div class="content">
                <p>你确认要退出本系统么?</p>
            </div>
            <div class="footer">
                <button @click="close">确认</button>
                <button @click="close">取消</button>
            </div>
        </div>
    </div>
</template>
  
  <script>
export default {
    props: {
        visable: Boolean
    },
    methods: {
        close() {
            this.$emit('update:visable', false)
        }
    }
}
</script>
  
  <style scoped>
.base-dialog-wrap {
    width: 300px;
    height: 200px;
    box-shadow: 2px 2px 2px 2px #ccc;
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    padding: 0 10px;
    z-index: 9;
    background-color: #fff;
}
.base-dialog .title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 2px solid #000;
}
.base-dialog .content {
    margin-top: 38px;
}
.base-dialog .title .close {
    width: 20px;
    height: 20px;
    cursor: pointer;
    line-height: 10px;
}
.footer {
    display: flex;
    justify-content: flex-end;
    margin-top: 26px;
}
.footer button {
    width: 80px;
    height: 40px;
}
.footer button:nth-child(1) {
    margin-right: 10px;
    cursor: pointer;
}
</style>


App.vue

<template>
    <div class="app">
        <button @click="isShow = true">退出按钮</button>
        <div :class="{ show_bg: isShow }">
            <SB :visable.sync="isShow"></SB>
            <!-- :visable.sync => :visable + @update:visable -->
        </div>
    </div>
</template>
  
  <script>
import SB from './components/SB.vue'
export default {
    data() {
        return {
            isShow: false
        }
    },
    methods: {},
    components: {
        SB
    }
}
</script>
  
<style>
.show_bg {
    position: absolute;
    top: 0;
    z-index: 2;
    width: 100%;
    height: 100%;
    background-color: #c4bbbba4;
}
</style>



ref 和 $refs

在这里插入图片描述

获取dom元素

<div ref="mychart" class="BaseEchart"></div>
 var myChart = echarts.init(this.$refs.mychart)

components/BaseEchart.vue

<template>
    <div ref="mychart" class="BaseEchart"></div>
</template>

<script>
import * as echarts from 'echarts'
export default {
    mounted() {
        // var myChart = echarts.init(document.querySelector('.BaseEchart'))
        var myChart = echarts.init(this.$refs.mychart)
        var option = {
            xAxis: {
                type: 'category',
                data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
            },
            yAxis: {
                type: 'value'
            },
            series: [
                {
                    data: [120, 200, 150, 80, 70, 110, 130],
                    type: 'bar'
                }
            ]
        }

        option && myChart.setOption(option)
    }
}
</script>

<!-- <style scoped> -->
<style >
.BaseEchart {
    width: 500px;
    height: 500px;
}
</style>


App.vue

<template>
    <div class="app">
        <div class="BaseEchart">捣乱的div</div>
        <BaseEchart></BaseEchart>
    </div>
</template>

<script>
import BaseEchart from './components/BaseEchart.vue'

export default {
    components: {
        BaseEchart
    }
}
</script>

<style  >
</style>


获取组件实例

在这里插入图片描述
componentes/BaseForm.vue

<template>
    <div class="BaseForm">
        用户名: <input v-model="username" type="text" /><br />
        密码: <input v-model="password" type="text" /><br />
    </div>
</template>

<script>
export default {
    data() {
        return {
            username: '',
            password: ''
        }
    },
    methods: {
        getValues() {
            return {
                username: this.username,
                psd: this.password
            }
        },
        clearValues() {
            this.username = ''
            this.password = ''
        }
    }
}
</script>

<style>
</style>


App.vue

<template>
    <div class="app">
        <BaseForm ref="Form"></BaseForm>
        <button @click="getDate">获取数据</button>
        <button @click="clearDate">清空数据</button>
    </div>
</template>

<script>
import BaseForm from './components/BaseForm.vue'
export default {
    components: {
        BaseForm
    },
    methods: {
        getDate() {
            console.log('www')

            console.log(this.$refs.Form.getValues())
        },
        clearDate() {
            this.$refs.Form.clearValues()
        }
    }
}
</script>

<style>
</style>


Vue 异步更新、$nextTick

在这里插入图片描述
App.vue

<template>
    <div class="app">
        <div v-if="isEdit">
            <input ref="inp" v-model="editValue" type="text" />
            <button @click="over">ok</button>
        </div>
        <div v-else>
            {{ title }}
            <button @click="changeTitle">edit</button>
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            editValue: '',
            title: '我是title',
            isEdit: false
        }
    },
    methods: {
        changeTitle() {
            // 1.显示输入框(异步dom更新
            this.isEdit = true

            // 2.让输入框获取焦点
            // $nextTick等dom更新完,立刻执行函数体
            this.$nextTick(() => {
                this.$refs.inp.focus()
            })
        },
        over() {
            this.title = this.editValue
            this.isEdit = false
        }
    }
}
</script>

<style>
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/843126.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单调队列-求一定范围内的最大值和最小值

一、链接 154. 滑动窗口 二、题目 给定一个大小为 n≤106n≤106 的数组。 有一个大小为 kk 的滑动窗口&#xff0c;它从数组的最左边移动到最右边。 你只能在窗口中看到 kk 个数字。 每次滑动窗口向右移动一个位置。 以下是一个例子&#xff1a; 该数组为 [1 3 -1 -3 5…

第九节 文件操作

文章目录 1. 引言2. 基本的文件操作2.1 打开文件2.1.1 mode 访问模式2.1.2 文件不存在,则创建文件2.1.3 二进制打开文件2.1.4 打开文件时&#xff0c;指定编码方式 2.2 关闭文件2.2.1 with 打开语句结构 2.3 文件的读写2.3.1 写入文件内容2.3.2 读取文件2.3.2.1 read&#xff0…

计算机网络-性能指标

计算机网络-性能指标 文章目录 计算机网络-性能指标简介速率比特速率 带宽吞吐量时延时延计算 时延带宽积往返时间网络利用率丢包率总结 简介 性能指标可以从不同的方面来度量计算机网络的性能 常用的计算机网络的性能指标有以下8个 速率带宽吞吐量时延时延带宽积往返时间利…

前端例程20230806:彩色灯珠装饰

演示 这里页面四周的彩色灯珠是会随着页面调整自动调整位置的。 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta na…

6.4.tensorRT高级(1)-UNet分割模型导出、编译到推理(无封装)

目录 前言1. Unet导出2. Unet推理总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-Unet分割模型导出、编译到…

【数据结构】Disruptor环形数组无锁并发框架阅读

Disruptor 是苹国外厂本易公司LMAX开发的一个高件能列&#xff0c;研发的初夷是解决内存队列的延识问顾在性能测试中发现竟然与10操作处于同样的数量级)&#xff0c;基于Disruptor开发的系统单线程能支撑每秒600万订单&#xff0c;2010年在QCn演讲后&#xff0c;获得了业界关注…

C++ 的 string 是用什么编码方式储存字符串的

代码 创建一个文件&#xff0c;用二进制的方式将字符串写入文件中 FileStream fs("test.txt", FileMode::Create);string str("测试文本");fs.Write((uint8_t *)str.c_str(), 0, str.length());return 0;其中 FileStream 是我对 fstream 的封装。 打开文…

p7付费课程笔记6:CMS GC

目录 前言 工作步骤 缺点 问题 前言 上一章节我们讲了串/并行GC&#xff0c;这一章节说下CMS GC。看前思考一个问题&#xff0c;并行GC与CMS GC的区别在哪里。 什么是CMS收集器 CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于…

2023年8月实时获取地图边界数据方法,省市区县街道多级联动【附实时geoJson数据下载】

首先&#xff0c;来看下效果图 在线体验地址&#xff1a;https://geojson.hxkj.vip&#xff0c;并提供实时geoJson数据文件下载 可下载的数据包含省级geojson行政边界数据、市级geojson行政边界数据、区/县级geojson行政边界数据、省市区县街道行政编码四级联动数据&#xff0…

PHP8条件控制语句-PHP8知识详解

我们昨天说了流程控制的结构有顺序结构、选择结构和循环结构。选择结构就是条件结构。 条件控制语句就是对语句中不同条件的值进行判断&#xff0c;进而根据不同的条件执行不同的语句。 在本文中&#xff0c;学习的是if语句、if…else语句、if…elseif语句和switch语句。 1、…

配置固定二级子域名远程访问内网群晖NAS 7.X版 【内网穿透】——“cpolar内网穿透”

配置固定二级子域名远程访问内网群晖NAS 7.X版 【内网穿透】 文章目录 配置固定二级子域名远程访问内网群晖NAS 7.X版 【内网穿透】前言1. 创建一条固定数据隧道2. 找到“保留二级子域名”栏位3. 重新编辑之前建立的临时数据隧道4. 进入“在线隧道列表”页面5. 在其他浏览器访问…

【山河送书第五期】:《码上行动:利用Python与ChatGPT高效搞定Excel数据分析》参与活动,送书三本!!

《码上行动&#xff1a;利用Python与ChatGPT高效搞定Excel数据分析》 前言内容提要本书亮点购买链接参与方式往期赠书回顾&#xff1a; 前言 在过去的 5 年里&#xff0c;Python 已经 3 次获得 TIOBE 指数年度大奖&#xff0c;这得益于数据科学和人工智能领域的发展&#xff0…

【MapGIS精品教程】010:空间叠置分析案例教程

文章目录 一、叠置分析介绍(一) 什么是叠加分析(二)叠加分析的分类二、叠加分析操作一、叠置分析介绍 (一) 什么是叠加分析 叠加分析是依靠把分散在不同层上的空间属性信息按相同的空间位置加到一起,合为新的一层。该层的属性由被叠加层各自的属性组合而成,这种组合可…

迈瑞监护仪ePM系列协议解析

ePM10 ePM12 ePM10M ePM12M等数据协议解析 生理参数解析如下&#xff1a; 波形数据解析如下&#xff1a;

100G光模块的应用案例分析:电信、云计算和大数据领域

100G光模块是一种高速光模块&#xff0c;由于其高速率和低延迟的特性&#xff0c;在电信、云计算和大数据领域得到了广泛的应用。在本文中&#xff0c;我们将深入探讨100G光模块在这三个领域的应用案例。 一、电信领域 在电信领域&#xff0c;100G光模块被广泛用于构建高速通…

SSL VPN

SSL工作过程 SSL&#xff08;Secure Sockets Layer&#xff0c;安全套接层&#xff09;是一种常用的加密协议 客户端发起连接请求&#xff1a;客户端向服务器发送连接请求&#xff0c;请求建立一个安全的SSL连接。 服务器响应&#xff1a;服务器接收到客户端的连接请求后&…

科技云报道:财税数字化时代,财务人实现RPA自由了吗?

企业数字化转型&#xff0c;财务是一个重要的切入点。随着数字化业务不断展开&#xff0c;新的系统、流程和数据源被不断引入&#xff0c;财务部门面临的是不断暴增的对账、处理报表、审计等日常工作。 如此大的工作量&#xff0c;即使是经验丰富的资深财务&#xff0c;也难免…

彩色CAD怎么转为黑白PDF?这些转换技巧了解一下

怎么将彩色CAD转换成黑白PDF格式呢&#xff1f;CAD文件方便编辑&#xff0c;但是不方便阅读和查看&#xff0c;将其转换成黑白色的PDF文件格式&#xff0c;浏览起来会更加方便&#xff0c;此外&#xff0c;黑白对比度高&#xff0c;使得其他人在查看或分享图纸时更容易阅读&…

【暑期每日一练】 Epilogue

目录 选择题&#xff08;1&#xff09;解析&#xff1a; &#xff08;2&#xff09;解析&#xff1a; &#xff08;3&#xff09;解析&#xff1a; &#xff08;4&#xff09;解析&#xff1a; &#xff08;5&#xff09;解析&#xff1a; 编程题题一描述输入描述&#xff1a;输…

科幻高大上的人脸识别接口

一、人脸登录系统特征识别&#x1f349; 采用人脸识别进行登陆验证&#xff0c;之后可选择步态识别数据录入或者在已经录入步态数据的情况下进行步态特征识别。这样的双重验证使得门禁系统更安全。 用户进入人脸识别区域后&#xff0c;系统将进行目标人物的人脸特征数据识别。…