Vue [Day4]

组件的三大组成部分

在这里插入图片描述

组件的样式冲突 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事件的合写

表单类组件封装

在这里插入图片描述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>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件外包开发的GO语言特点

Go语言&#xff08;也称为Golang&#xff09;是由Google开发的一种编程语言。它具有许多特点&#xff0c;使其成为许多项目范围的优秀选择。Go语言适用于需要高性能、并发和简洁易读的项目&#xff0c;特别是面向网络和分布式应用的项目。今天和大家分享项目的特点及适用的项目…

【深度学习环境】安装anaconda、tensorflow、pycharm

目录 1.安装anaconda 2.安装tensorflow-gpu 3.安装pycharm 4.VNC操作 5.安装Pytorch PS: linux下常见的操作&#xff1a; 1.Linux下强制关闭程序&#xff1a; 2.导出环境 2.1.pip导出 2.2.conda导出 2.3.其他 3.windows下的环境安装 & pycharm远程配置 4.bash…

postman和jmeter的区别何在?

小伙伴们大家好呀&#xff0c;前段时间笔者做了一个小调查&#xff0c;发现软件测试行业做功能测试和接口测试的人相对比较多。在测试工作中&#xff0c;有高手&#xff0c;自然也会有小白&#xff0c;但有一点我们无法否认&#xff0c;就是每一个高手都是从小白开始的&#xf…

BS框架说明

B/S架构 1.B/S框架&#xff0c;意思是前端&#xff08;Browser 浏览器&#xff0c;小程序、app、自己写的&#xff09;和服务器端&#xff08;Server&#xff09;组成的系统的框架结构 2.B/S框架&#xff0c;也可理解为web架构&#xff0c;包含前端、后端、数据库三大组成部分…

数据可视化(七)常用图表的绘制

1. #seaborn绘制常用图表 #折线图 #replot&#xff08;x&#xff0c;y&#xff0c;kind&#xff0c;data&#xff09; #lineplot&#xff08;x&#xff0c;y&#xff0c;data&#xff09; #直方图 #displot&#xff08;data&#xff0c;rug&#xff09; #条形图 #barplot&…

测试老鸟总结,性能测试需求分析-性能必要性,一篇打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 性能测试需求分析…

基于react-native的简单消息确认框showModel

基于react-native的简单消息确认框showModel 效果示例图组件代码ShowModel/index.jsx使用案例device.js安装线性渐变色 效果示例图 组件代码ShowModel/index.jsx import React, {forwardRef, useImperativeHandle, useState} from react; import {View,Text,Modal,TouchableOp…

Babylon.js开发工具链大全

本文介绍Babylon 团队&#xff08;JS 和原生&#xff09;和社区共同创建的所有出色工具的摘要&#xff0c;以帮助开发人员和设计人员创建出色的 3D 体验。 推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D场景。 1、Sandbox 第一个工具Sandbox可能是最简单的&#xff0c;它实…

基于RASC的keil电子时钟制作(瑞萨RA)(8)----按键修改数码管时间

基于RASC的keil电子时钟制作8_按键修改数码管时间 概述硬件准备视频教程配置按键管脚按键设置主程序timer_smg.ctimer_smg.h 概述 前几节课程已经单独驱动了数码管和RTC&#xff0c;同时已经整合成了能够用数码管显示具体时间&#xff0c;但是无法修改时间&#xff0c;这节就来…

web基础与tomcat环境部署

一. 简述静态网页和动态网页的区别。 请求响应信息&#xff0c;发给客户端进行处理&#xff0c;由浏览器进行解析&#xff0c;显示的页面称为静态页面。处理文件类型如.html、jpg、.gif、.mp4、.swf、.avi、.wmv、.flv等 请求响应信息&#xff0c;发给事务端进行处理&#xff0…

信号平滑或移动平均滤波研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

数据库与数据仓库的区别及关系

数据库与数据仓库的区别及关系 数据库数据仓库异同差异联系例子 数据库 数据库是结构化信息或数据的有序集合&#xff0c;一般以电子形式存储在计算机系统中。通常由数据库管理系统 (DBMS) 来控制。它是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集…

【导出Word】如何使用Java+Freemarker模板引擎,根据XML模板文件生成Word文档(只含文本内容的模板)

这篇文章&#xff0c;主要介绍如何使用JavaFreemarker模板引擎&#xff0c;根据XML模板文件生成Word文档。 目录 一、导出Word文档 1.1、基础知识 1.2、制作模板文件 1.3、代码实现 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;创建Freemarker工具类 &…

VL 模型 Open-Set Domain Adaptation with Visual-Language Foundation Models 论文阅读笔记

Open-Set Domain Adaptation with Visual-Language Foundation Models 论文阅读笔记 一、Abstract 写在前面 又是一周周末&#xff0c;在家的时间感觉过得很快呀。今天没得时间写博客&#xff0c;留下个标题&#xff0c;明天搞完。 论文地址&#xff1a;Open-Set Domain Adapta…

Windows上安装 jdk 环境并配置环境变量 (超详细教程)

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…

HDFS中的NAMENODE元数据管理(超详细)

元数据管理 元数据是什么元数据管理概述内存元数据元数据文件fsimage内存镜像文件edits log编辑日志 namenode加载元数据文件顺序 元数据管理相关目录文件元数据相关文件VERSIONseen_txid 元数据文件查看&#xff08;OIV,OEV&#xff09;SecondaryNameNode介绍checkpoint机制SN…

uC-OS2 V2.93 STM32L476 移植:系统启动篇

前言 前两篇已经 通过 STM32CubeMX 搭建了 NUCLEO-L476RG 的 STM32L476RG 的 裸机工程&#xff0c;下载了 uC-OS2 V2.93 的源码&#xff0c;并把 uC-OS2 的源文件加入 Keil MDK5 工程 本篇适配 uC-OS2 的 系统定时器&#xff08;Systick&#xff09;与 PendSV_Handler&#xf…

【C#学习笔记】类型转换

文章目录 类型转换字符转数字GetNumericValueConvert.ToInt32隐式转换计算 字符串转数字Parse 或 TryParse 方法 字节数组转整数 as&#xff0c;is强制类型转换isas 用户定义的转换 类型转换 我们简单地将值类型分为5种&#xff1a;整数型&#xff0c;浮点型&#xff0c;布尔型…

增强型Web安全网关在银行的应用

销售&#xff0c;绝不是降低身份去取悦客户&#xff0c;而是像朋友一样给予合理的建议。你刚好需要&#xff0c;我刚好专业&#xff01;仅此而已&#xff01; 乔.吉拉德 健康的安全体系&#xff0c;还可以更完善 浙江某商业银行股份有限公司是一家成立多年的商业银行&#xf…

抖音seo源码开发源代码搭建分享

抖音SEO源码开发涉及到以下几个方面&#xff1a; 前端开发&#xff1a;包括抖音SEO页面的设计与布局&#xff0c;以及需要使用到的前端技术&#xff0c;如HTML、CSS、JavaScript等。 后端开发&#xff1a;包括抖音SEO页面的数据获取和处理&#xff0c;以及需要使用到的后端技术…