Vue 基础使用 笔记

82 阅读1分钟

1 表达式

  1. 插值, 表达式

  2. 指令, 动态属性

  3. v-html 有xss风险

<template>
    <div>
        <p>文本插值 {{message}}</p>
        <p>JS 表达式 {{ flag ? 'yes' : 'no' }} (只能是表达式,不能是 js 语句)</p>

        <p :id="dynamicId">动态属性 id</p>

        <hr/>
        <p v-html="rawHtml">
            <span>有 xss 风险</span>
            <span>【注意】使用 v-html 之后,将会覆盖子元素</span>
        </p>
    </div>
</template>

<script>
export default {
    data() {
        return {
            message: 'hello vue',
            flag: true,
            rawHtml: '指令 - 原始 html <b>加粗</b> <i>斜体</i>',
            dynamicId: `id-${Date.now()}`
        }
    }
}
</script>

2 computed 和 watch

  1. computed 有缓存, data 不变则不会重新计算

    <template>
     <div>
         <p>num {{num}}</p>
         <p>double1 {{double1}}</p>
         <input v-model="double2"/>
     </div>
    </template>
    
     <script>
     export default {
         data() {
             return {
                 num: 20
             }
         },
         computed: {
             double1() {
                 return this.num * 2
             },
             double2: {
                 get() {
                     return this.num * 2
                 },
                 set(val) {
                     this.num = val/2
                 }
             }
         }
     }
     </script>
    
  2. watch 如何深度箭头

  3. watch 监听引用类型, 拿不到old value

            <template>
        <div>
            <input v-model="name"/>
            <input v-model="info.city"/>
        </div>
    </template>

    <script>
    export default {
        data() {
            return {
                name: '双越',
                info: {
                    city: '北京'
                }
            }
        },
        watch: {
            name(oldVal, val) {
                // eslint-disable-next-line
                console.log('watch name', oldVal, val) // 值类型,可正常拿到 oldVal 和 val
            },
            info: {
                handler(oldVal, val) {
                    // eslint-disable-next-line
                    console.log('watch info', oldVal, val) // 引用类型,拿不到 oldVal 。因为指针相同,此时已经指向了新的 val
                },
                deep: true // 深度监听
            }
        }
    }
    </script>

3 class 和 style

  1. 动态属性
  2. 驼峰写法
<template>
    <div>
        <p :class="{ black: isBlack, yellow: isYellow }">使用 class</p>
        <p :class="[black, yellow]">使用 class (数组)</p>
        <p :style="styleData">使用 style</p>
    </div>
</template>

<script>
export default {
    data() {
        return {
            isBlack: true,
            isYellow: true,

            black: 'black',
            yellow: 'yellow',

            styleData: {
                fontSize: '40px', // 转换为驼峰式
                color: 'red',
                backgroundColor: '#ccc' // 转换为驼峰式
            }
        }
    }
}
</script>

<style scoped>
    .black {
        background-color: #999;
    }
    .yellow {
        color: yellow;
    }
</style>

4 条件渲染

  1. v-if v-else 的用法
  2. v-if 和 v-show 的区别
  3. v-if 和 v-show 的使用场景

    <template>
    <div>
        <p v-if="type === 'a'">A</p>
        <p v-else-if="type === 'b'">B</p>
        <p v-else>other</p>

        <p v-show="type === 'a'">A by v-show</p>
        <p v-show="type === 'b'">B by v-show</p>
    </div>
</template>

<script>
export default {
    data() {
        return {
            type: 'a'
        }
    }
}
</script>

频繁切换, 使用v-show, 更新不频繁, v-show 和 v-if 都可以, 弹出框关闭的时候想要弹出框的组件也销毁, 可是在弹出框中使用v-if

5 循环列表渲染

  1. 遍历对象
  2. key 的重要性(不能使用random 和 index)
  3. v-if 和 v-for 不能同时使用
<template>
    <div>
        <p>遍历数组</p>
        <ul>
            <li v-for="(item, index) in listArr" :key="item.id">
                {{index}} - {{item.id}} - {{item.title}}
            </li>
        </ul>

        <p>遍历对象</p>
        <ul >
            <li v-for="(val, key, index) in listObj" :key="key">
                {{index}} - {{key}} -  {{val.title}}
            </li>
        </ul>
    </div>
</template>

<script>
export default {
    data() {
        return {
            flag: false,
            listArr: [
                { id: 'a', title: '标题1' }, // 数据结构中,最好有 id ,方便使用 key
                { id: 'b', title: '标题2' },
                { id: 'c', title: '标题3' }
            ],
            listObj: {
                a: { title: '标题1' },
                b: { title: '标题2' },
                c: { title: '标题3' },
            }
        }
    }
}
</script>

v-for 的优先级高于v-if

6 事件

  1. evnt参数,自定义参数
  2. 事件修饰符, 按键修饰符
  3. 观察 事件被绑定到哪里

<template>
    <div>
        <p>{{num}}</p>
        <button @click="increment1">+1</button>
        <button @click="increment2(2, $event)">+2</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            num: 0
        }
    },
    methods: {
        increment1(event) {
            // eslint-disable-next-line
            console.log('event', event, event.__proto__.constructor) // 是原生的 event 对象
            // eslint-disable-next-line
            console.log(event.target)
            // eslint-disable-next-line
            console.log(event.currentTarget) // 注意,事件是被注册到当前元素的,和 React 不一样
            this.num++

            // 1. event 是原生的
            // 2. 事件被挂载到当前元素
        },
        increment2(val, event) {
            // eslint-disable-next-line
            console.log(event.target)
            this.num = this.num + val
        },
        loadHandler() {
            // do some thing
        }
    },
    mounted() {
        window.addEventListener('load', this.loadHandler)
    },
    beforeDestroy() {
        // 自己绑定的事件,需要自己销毁!!!
        window.removeEventListener('load', this.loadHandler)
    }
}
</script>


事件修饰符

    // 阻止单击事件传播
    <a v-on:click.stop="doThis"></a>
    // 提交后不在重载页面
    <from v-on:submit.prevent="submit"></from>
    
    // 内部事件元触发事件先在这里处理, 然后再由内部元素处理
    <div v-on:click.capture="doThis"></div>
    
    // 事件不是内部元素出发的
    <div v-on:click.self="doThis"></div>
    
    // ctrl 被按下时才触发
    <button @click.ctrl="onclick"></button>
    // 只ctrl 被按下时才触发 
    <button @click.ctrl.exact="onclick"></button>
    // 没有任何按键被按下时才触发
    <button @click.exact="onclick"></button>

7 表单

    <template>
    <div>
        <p>输入框: {{name}}</p>
        <input type="text" v-model.trim="name"/>
        <input type="text" v-model.lazy="name"/>
        <input type="text" v-model.number="age"/>

        <p>多行文本: {{desc}}</p>
        <textarea v-model="desc"></textarea>
        <!-- 注意,<textarea>{{desc}}</textarea> 是不允许的!!! -->

        <p>复选框 {{checked}}</p>
        <input type="checkbox" v-model="checked"/>

        <p>多个复选框 {{checkedNames}}</p>
        <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>

        <p>单选 {{gender}}</p>
        <input type="radio" id="male" value="male" v-model="gender"/>
        <label for="male">男</label>
        <input type="radio" id="female" value="female" v-model="gender"/>
        <label for="female">女</label>

        <p>下拉列表选择 {{selected}}</p>
        <select v-model="selected">
            <option disabled value="">请选择</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>

        <p>下拉列表选择(多选) {{selectedList}}</p>
        <select v-model="selectedList" multiple>
            <option disabled value="">请选择</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>
    </div>
</template>

<script>
export default {
    data() {
        return {
            name: 'zehui',
            age: 22,
            desc: '自我介绍',

            checked: true,
            checkedNames: [],

            gender: 'male',

            selected: '',
            selectedList: []
        }
    }
}
</script>