Vue.js 核心知识点完整解析第一章

1. Vue模板语法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue模板语法</title>
    <script src="../static/js/vue.js"></script>
</head>
<body>
    <div id="root">
        <!-- 插值语法:用于解析标签体内容 -->
        <h1>插值语法示例</h1>
        <p>{{ message }}</p>
        <p>{{ number + 1 }}</p>
        <p>{{ ok ? 'YES' : 'NO' }}</p>
        <p>{{ message.split('').reverse().join('') }}</p>
        
        <!-- 指令语法:用于解析标签属性、内容、事件等 -->
        <h1>指令语法示例</h1>
        <!-- v-bind 指令 -->
        <a v-bind:href="url">普通绑定</a>
        <a :href="url">简写绑定</a>
        <div :class="className">类名绑定</div>
        <div :style="styleObject">样式绑定</div>
        
        <!-- v-on 指令 -->
        <button v-on:click="handleClick">普通事件</button>
        <button @click="handleClick">简写事件</button>
        
        <!-- v-if 指令 -->
        <p v-if="show">条件渲染</p>
        
        <!-- v-for 指令 -->
        <ul>
            <li v-for="item in items" :key="item.id">{{ item.name }}</li>
        </ul>
    </div>

    <script>
        new Vue({
            el: '#root',
            data: {
                message: 'Hello Vue!',
                number: 10,
                ok: true,
                url: 'https://vuejs.org',
                className: 'active',
                styleObject: {
                    color: 'red',
                    fontSize: '20px'
                },
                show: true,
                items: [
                    { id: 1, name: 'Vue' },
                    { id: 2, name: 'React' },
                    { id: 3, name: 'Angular' }
                ]
            },
            methods: {
                handleClick() {
                    alert('按钮被点击了!');
                }
            }
        });
    </script>
</body>
</html>

知识点总结:

  • 插值语法:{{ }} 用于标签体内容,支持JS表达式
  • 指令语法:v- 前缀的特殊属性,用于各种DOM操作
  • 常用指令:v-bind, v-on, v-if, v-for
  • 简写形式:: 代替 v-bind, @ 代替 v-on

2. 数据绑定与el/data的两种写法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数据绑定与写法</title>
    <script src="../static/js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h1>数据绑定示例</h1>
        
        <!-- 单向数据绑定:v-bind -->
        <input type="text" v-bind:value="name">
        <span>单向绑定:{{name}}</span>
        
        <!-- 双向数据绑定:v-model -->
        <input type="text" v-model="name">
        <span>双向绑定:{{name}}</span>
        
        <!-- v-model修饰符 -->
        <input v-model.lazy="lazyText" placeholder="懒更新">
        <input v-model.number="numberText" placeholder转为数字>
        <input v-model.trim="trimText" placeholder="去除空格">
    </div>

    <script>
        // el的两种写法
        const vm = new Vue({
            // 写法一:直接配置el属性
            // el: '#root',
            
            data: {
                name: 'Vue.js',
                lazyText: '',
                numberText: '',
                trimText: ''
            },
            
            // 写法二:使用$mount()
            // mounted() {
            //     this.$mount('#root');
            // }
        });
        
        // 第二种el写法
        vm.$mount('#root');
        
        // data的两种写法
        const vm2 = new Vue({
            el: '#app',
            // 写法一:对象式
            // data: {
            //     name: '对象式data'
            // }
            
            // 写法二:函数式(推荐)
            data() {
                return {
                    name: '函数式data'
                };
            }
        });
    </script>
</body>
</html>

知识点总结:

  • 单向绑定v-bind 数据从Vue流向页面
  • 双向绑定v-model 数据双向流动
  • el的两种写法:配置对象中直接写 / 使用$mount()
  • data的两种写法:对象式 / 函数式(组件必须用函数式)

3. MVVM模型与数据代理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MVVM与数据代理</title>
    <script src="../static/js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h1>MVVM模型演示</h1>
        <p>Model: {{message}}</p>
        <input v-model="message" placeholder="修改Model">
        
        <h2>数据代理验证</h2>
        <p>原始数据: {{originalData}}</p>
        <p>代理后数据: {{proxyData}}</p>
    </div>

    <script>
        // MVVM模型理解
        const vm = new Vue({
            el: '#root',
            data: {
                message: 'Hello MVVM',
                originalData: '原始值'
            },
            computed: {
                // 数据代理示例
                proxyData: {
                    get() {
                        return this.originalData + ' (代理后)';
                    },
                    set(value) {
                        this.originalData = value.replace(' (代理后)', '');
                    }
                }
            }
        });

        // 验证数据代理
        console.log(vm); // 查看Vue实例
        console.log(vm._data === vm.$data); // true
        console.log(vm.message === vm._data.message); // true,证明数据代理
    </script>
</body>
</html>

知识点总结:

  • MVVM模型:Model-View-ViewModel的缩写
  • M:模型,对应data中的数据
  • V:视图,模板DOM
  • VM:视图模型,Vue实例对象
  • 数据代理:通过Object.defineProperty()实现,vm代理data中属性的操作

4. 事件处理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件处理</title>
    <script src="../static/js/vue.js"></script>
    <style>
        .demo { width: 100px; height: 100px; background: skyblue; margin: 10px; }
    </style>
</head>
<body>
    <div id="root">
        <h1>事件处理大全</h1>
        
        <!-- 基本事件处理 -->
        <button @click="showAlert">点击事件</button>
        <button @click="showMessage('参数传递')">带参数事件</button>
        
        <!-- 事件修饰符 -->
        <div @click="outerClick" class="demo">
            <div @click.stop="innerClick" class="demo">.stop阻止冒泡</div>
        </div>
        
        <a @click.prevent="linkClick" href="https://vuejs.org">.prevent阻止默认行为</a>
        
        <!-- 键盘事件 -->
        <input @keyup.enter="enterPressed" placeholder="按回车触发">
        <input @keyup.13="enterPressed" placeholder="按键码13也是回车">
        
        <!-- 鼠标事件 -->
        <div @mouseenter="mouseEnter" @mouseleave="mouseLeave" class="demo">
            鼠标事件
        </div>
        
        <!-- 事件对象 -->
        <button @click="eventHandler">事件对象$event</button>
        <button @click="eventHandler2($event, '自定义参数')">混合参数</button>
    </div>

    <script>
        new Vue({
            el: '#root',
            methods: {
                showAlert() {
                    alert('按钮被点击了!');
                },
                showMessage(msg) {
                    alert('收到消息:' + msg);
                },
                outerClick() {
                    console.log('外部div被点击');
                },
                innerClick() {
                    console.log('内部div被点击,不会冒泡到外部');
                },
                linkClick() {
                    alert('链接被点击,但不会跳转');
                },
                enterPressed() {
                    console.log('回车键被按下');
                },
                mouseEnter() {
                    console.log('鼠标进入');
                },
                mouseLeave() {
                    console.log('鼠标离开');
                },
                eventHandler(event) {
                    console.log('事件对象:', event);
                    console.log('目标元素:', event.target);
                },
                eventHandler2(event, param) {
                    console.log('事件对象:', event);
                    console.log('自定义参数:', param);
                }
            }
        });
    </script>
</body>
</html>

知识点总结:

  • 事件绑定v-on@ 简写
  • 事件修饰符.stop, .prevent, .capture, .self, .once, .passive
  • 按键修饰符.enter, .tab, .delete, .esc, .space, .up, .down, .left, .right
  • 系统修饰键.ctrl, .alt, .shift, .meta

5. 计算属性与监视属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>计算属性与监视属性</title>
    <script src="../static/js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h1>计算属性 vs 方法 vs 监视属性</h1>
        
        <input v-model="firstName" placeholder="">
        <input v-model="lastName" placeholder="">
        
        <h3>方法调用:{{getFullName()}}</h3>
        <h3>计算属性:{{fullName}}</h3>
        <h3>监视结果:{{watchedFullName}}</h3>
        
        <h2>购物车示例</h2>
        <div v-for="item in cart" :key="item.id">
            {{item.name}} - ¥{{item.price}} × {{item.quantity}}
        </div>
        <h3>总价(计算属性):¥{{totalPrice}}</h3>
        <h3>总价(监视属性):¥{{watchedTotalPrice}}</h3>
    </div>

    <script>
        new Vue({
            el: '#root',
            data: {
                firstName: '张',
                lastName: '三',
                watchedFullName: '',
                watchedTotalPrice: 0,
                cart: [
                    { id: 1, name: '商品A', price: 100, quantity: 2 },
                    { id: 2, name: '商品B', price: 200, quantity: 1 }
                ]
            },
            methods: {
                getFullName() {
                    console.log('方法被调用');
                    return this.firstName + this.lastName;
                }
            },
            computed: {
                // 计算属性:有缓存,依赖变化才重新计算
                fullName: {
                    get() {
                        console.log('计算属性被调用');
                        return this.firstName + this.lastName;
                    },
                    set(value) {
                        const names = value.split('');
                        this.firstName = names[0];
                        this.lastName = names[1] || '';
                    }
                },
                totalPrice() {
                    return this.cart.reduce((total, item) => {
                        return total + item.price * item.quantity;
                    }, 0);
                }
            },
            watch: {
                // 监视属性:数据变化时执行异步或复杂操作
                firstName: {
                    handler(newVal, oldVal) {
                        console.log('firstName从', oldVal, '变为', newVal);
                        this.watchedFullName = newVal + this.lastName;
                    },
                    immediate: true // 立即执行一次
                },
                lastName: {
                    handler(newVal) {
                        this.watchedFullName = this.firstName + newVal;
                    }
                },
                cart: {
                    handler() {
                        this.watchedTotalPrice = this.cart.reduce((total, item) => {
                            return total + item.price * item.quantity;
                        }, 0);
                    },
                    deep: true // 深度监视
                }
            }
        });
    </script>
</body>
</html>

知识点总结:

  • 计算属性:基于依赖缓存,只有相关依赖发生改变时才会重新求值
  • 监视属性:观察和响应Vue实例上的数据变动,适合执行异步操作
  • 区别:计算属性适合同步计算,监视属性适合异步或复杂逻辑

6. 绑定样式与条件渲染

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>样式绑定与条件渲染</title>
    <script src="../static/js/vue.js"></script>
    <style>
        .basic { padding: 10px; margin: 5px; }
        .active { background-color: #4CAF50; color: white; }
        .text-danger { color: red; }
        .large { font-size: 24px; }
        .rounded { border-radius: 10px; }
        
        .static-class { border: 1px solid #ccc; }
        
        .v-enter-active, .v-leave-active {
            transition: opacity 0.5s;
        }
        .v-enter, .v-leave-to {
            opacity: 0;
        }
    </style>
</head>
<body>
    <div id="root">
        <h1>样式绑定</h1>
        
        <!-- 绑定class - 对象语法 -->
        <div class="basic" :class="{ active: isActive, 'text-danger': hasError }">
            对象语法:{{isActive ? '激活' : '未激活'}}
        </div>
        
        <!-- 绑定class - 数组语法 -->
        <div class="basic" :class="[activeClass, errorClass]">
            数组语法:同时绑定多个class
        </div>
        
        <!-- 绑定style - 对象语法 -->
        <div :style="{ color: activeColor, fontSize: fontSize + 'px' }">
            内联样式对象语法
        </div>
        
        <!-- 绑定style - 数组语法 -->
        <div :style="[baseStyles, overridingStyles]">
            内联样式数组语法
        </div>
        
        <h1>条件渲染</h1>
        
        <!-- v-if vs v-show -->
        <button @click="show = !show">切换显示</button>
        
        <div v-if="show" class="basic">v-if条件渲染(元素移除)</div>
        <div v-show="show" class="basic">v-show条件渲染(display切换)</div>
        
        <!-- v-if、v-else-if、v-else -->
        <div>
            <input type="number" v-model="score" placeholder="输入分数">
            <div v-if="score >= 90">优秀</div>
            <div v-else-if="score >= 80">良好</div>
            <div v-else-if="score >= 60">及格</div>
            <div v-else>不及格</div>
        </div>
        
        <!-- template标签使用 -->
        <template v-if="showTemplate">
            <h3>Template标签</h3>
            <p>这组元素会一起显示或隐藏</p>
        </template>
        
        <!-- 用key管理可复用的元素 -->
        <template v-if="loginType === 'username'">
            <label>用户名:</label>
            <input placeholder="输入用户名" key="username-input">
        </template>
        <template v-else>
            <label>邮箱:</label>
            <input placeholder="输入邮箱" key="email-input">
        </template>
        <button @click="toggleLoginType">切换登录方式</button>
    </div>

    <script>
        new Vue({
            el: '#root',
            data: {
                // 样式数据
                isActive: true,
                hasError: false,
                activeClass: 'active',
                errorClass: 'text-danger',
                activeColor: 'blue',
                fontSize: 20,
                baseStyles: {
                    padding: '10px',
                    margin: '5px'
                },
                overridingStyles: {
                    backgroundColor: '#f0f0f0',
                    borderRadius: '5px'
                },
                
                // 条件渲染数据
                show: true,
                score: 85,
                showTemplate: true,
                loginType: 'username'
            },
            methods: {
                toggleLoginType() {
                    this.loginType = this.loginType === 'username' ? 'email' : 'username';
                }
            }
        });
    </script>
</body>
</html>

知识点总结:

  • class绑定:对象语法、数组语法
  • style绑定:对象语法、数组语法
  • v-if:真正的条件渲染,确保事件监听器和子组件适当被销毁和重建
  • v-show:只是简单地切换元素的CSS display属性
  • 选择建议:频繁切换用v-show,运行时条件很少改变用v-if

7. 列表渲染与表单数据收集

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>列表渲染与表单数据</title>
    <script src="../static/js/vue.js"></script>
    <style>
        .list-item { padding: 10px; border: 1px solid #ddd; margin: 5px; }
        .completed { text-decoration: line-through; color: #999; }
        .form-group { margin: 10px 0; }
        label { display: inline-block; width: 100px; }
    </style>
</head>
<body>
    <div id="root">
        <h1>列表渲染 v-for</h1>
        
        <!-- 数组渲染 -->
        <h3>用户列表</h3>
        <ul>
            <li v-for="(user, index) in users" :key="user.id">
                {{index + 1}}. {{user.name}} - {{user.age}}岁
                <button @click="removeUser(index)">删除</button>
            </li>
        </ul>
        
        <!-- 对象渲染 -->
        <h3>用户信息对象</h3>
        <div v-for="(value, key, index) in userInfo" :key="key">
            {{index}}. {{key}} : {{value}}
        </div>
        
        <!-- 范围渲染 -->
        <h3>数字范围</h3>
        <span v-for="n in 5" :key="n">{{n}} </span>
        
        <!-- 过滤/排序列表 -->
        <h3>成年用户(计算属性过滤)</h3>
        <ul>
            <li v-for="user in adultUsers" :key="user.id">
                {{user.name}} - {{user.age}}岁
            </li>
        </ul>
        
        <h1>表单数据收集</h1>
        
        <form @submit.prevent="handleSubmit">
            <!-- 文本输入 -->
            <div class="form-group">
                <label>用户名:</label>
                <input type="text" v-model.trim="formData.username">
            </div>
            
            <!-- 密码输入 -->
            <div class="form-group">
                <label>密码:</label>
                <input type="password" v-model="formData.password">
            </div>
            
            <!-- 单选按钮 -->
            <div class="form-group">
                <label>性别:</label>
                <input type="radio" id="male" value="male" v-model="formData.gender">
                <label for="male"></label>
                <input type="radio" id="female" value="female" v-model="formData.gender">
                <label for="female"></label>
            </div>
            
            <!-- 复选框 -->
            <div class="form-group">
                <label>爱好:</label>
                <input type="checkbox" id="basketball" value="basketball" v-model="formData.hobbies">
                <label for="basketball">篮球</label>
                <input type="checkbox" id="football" value="football" v-model="formData.hobbies">
                <label for="football">足球</label>
                <input type="checkbox" id="swimming" value="swimming" v-model="formData.hobbies">
                <label for="swimming">游泳</label>
            </div>
            
            <!-- 选择框 -->
            <div class="form-group">
                <label>城市:</label>
                <select v-model="formData.city">
                    <option value="">请选择</option>
                    <option value="beijing">北京</option>
                    <option value="shanghai">上海</option>
                    <option value="guangzhou">广州</option>
                </select>
            </div>
            
            <!-- 多行文本 -->
            <div class="form-group">
                <label>个人介绍:</label>
                <textarea v-model.lazy="formData.introduction"></textarea>
            </div>
            
            <button type="submit">提交</button>
        </form>
        
        <h3>表单数据预览:</h3>
        <pre>{{ JSON.stringify(formData, null, 2) }}</pre>
    </div>

    <script>
        new Vue({
            el: '#root',
            data: {
                // 列表数据
                users: [
                    { id: 1, name: '张三', age: 25 },
                    { id: 2, name: '李四', age: 17 },
                    { id: 3, name: '王五', age: 30 },
                    { id: 4, name: '赵六', age: 16 }
                ],
                userInfo: {
                    name: '张三',
                    age: 25,
                    gender: 'male',
                    city: 'beijing'
                },
                
                // 表单数据
                formData: {
                    username: '',
                    password: '',
                    gender: 'male',
                    hobbies: [],
                    city: '',
                    introduction: ''
                }
            },
            computed: {
                adultUsers() {
                    return this.users.filter(user => user.age >= 18);
                }
            },
            methods: {
                removeUser(index) {
                    this.users.splice(index, 1);
                },
                handleSubmit() {
                    // 表单验证
                    if (!this.formData.username.trim()) {
                        alert('请输入用户名');
                        return;
                    }
                    
                    if (this.formData.hobbies.length === 0) {
                        alert('请至少选择一个爱好');
                        return;
                    }
                    
                    // 提交逻辑
                    console.log('表单数据:', this.formData);
                    alert('表单提交成功!');
                    
                    // 重置表单
                    this.formData = {
                        username: '',
                        password: '',
                        gender: 'male',
                        hobbies: [],
                        city: '',
                        introduction: ''
                    };
                }
            }
        });
    </script>
</body>
</html>

知识点总结:

  • 列表渲染v-for 指令遍历数组、对象、数字范围
  • key的重要性:为每个节点提供唯一标识,优化虚拟DOM的diff算法
  • 数组更新检测:Vue包装了数组的变异方法,能触发视图更新
  • 表单绑定v-model 在各种表单元素上的应用
  • 修饰符.lazy, .number, .trim 的使用场景

核心知识点回顾

Vue实例与配置

  • el:指定挂载目标,两种写法
  • data:数据对象,两种写法(对象式/函数式)
  • methods:定义方法,this自动绑定为Vue实例

数据绑定与响应式

  • 插值语法{{ }} 用于文本内容
  • 指令语法v- 前缀的特殊属性
  • 双向绑定v-model 实现表单输入与应用状态同步

计算属性与监视

  • computed:基于依赖缓存,适合计算逻辑
  • watch:观察数据变化,适合异步操作

条件与列表渲染

  • v-if/v-show:条件渲染,注意区别
  • v-for:列表渲染,必须使用key

样式与类绑定

  • :class:动态绑定CSS类
  • :style:动态绑定内联样式

事件处理

  • v-on:事件监听,支持修饰符
  • 事件对象$event 的使用

这些知识点构成了Vue.js的基础核心,掌握好这些内容为进一步学习Vue组件化开发打下坚实基础。

生活感悟

这周学习Vue基础时,发现理解概念和实际编码是两回事。看视频觉得都懂了,一写代码就遇到各种问题。最大的体会是:不能光看,一定要动手敲代码。每个小知识点都要亲自验证,犯错越多,收获越大。
**

学习计划

**
一:过滤器

学习过滤器的定义和使用

实践:日期格式化、价格显示等常用过滤器

目标:掌握{{ message | filterName }}语法

二:内置指令

重点指令:v-text、v-html、v-cloak、v-once、v-pre

理解每个指令的应用场景和注意事项

特别注意v-html的安全问题

三:自定义指令

学习指令的注册方式(全局/局部)

掌握5个钩子函数:bind、inserted、update等

实践:实现一个自动聚焦指令

四:生命周期

记忆8个关键生命周期钩子

理解每个阶段适合做什么操作

避免在created中操作DOM

五:非单文件组件

组件的基本定义和注册

组件间的数据传递(props/$emit)

理解组件化开发思想

六:单文件组件

学习.vue文件的结构(template、script、style)

搭建Vue CLI开发环境

体验现代前端开发流程

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐