Vue 基础

Vue.js 介绍

Vue.js 是一个用于构建用户界面的渐进式框架。它的核心库专注于视图层,易于学习,与其他库或已有项目结合非常灵活。Vue 采用了 MVVM(Model-View-ViewModel)模式,使得开发者能够通过声明式渲染和数据双向绑定来简化开发工作。

环境搭建

使用 CDN 快速体验

你可以在 HTML 文件中直接通过 CDN 引入 Vue.js,这样可以快速开始体验 Vue.js 的基本功能。

确保你在 <head> 部分引入了 Vue.js。如果你使用的是 CDN,确保 URL 正确,并且在 Vue.js 加载完成后再创建 Vue 实例。正确的引用应该像这样:

<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>

示例 HTML 源码:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js 入门示例</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <!-- 引入 Vue.js -->
</head>
<body>
    <div id="app"> <!-- Vue 实例挂载的 DOM 元素 -->
        <h1>{{ message }}</h1> <!-- 数据绑定显示 -->
    </div>

    <script>
        new Vue({
            el: '#app',  // 将 Vue 实例挂载到 id 为 app 的 DOM 元素上
            data: {
                message: 'Hello Vue!' // Vue 实例的数据对象
            }
        });
    </script>
</body>
</html>

使用 Vue CLI 创建项目

Vue CLI 是一个官方提供的工具,可以帮助你快速生成 Vue 项目结构。

确保你已经在电脑上安装了Node.js。Node.js 的安装包中会包含 npm(Node 包管理器),你可以使用 npm 来安装 Vue CLI。输入以下命令检查 Node.js 和 npm 是否安装成功:

node -v
npm -v

安装 Vue CLI:

npm install -g @vue/cli

创建新项目:

使用命令为你的应用创建新的项目(假设项目名为 my-project):

vue create my-project

进入项目目录并启动开发服务器:

cd my-project
npm run serve

可以在 VSCode 中点击左边的“文件”菜单,选择“打开文件夹”,找到并选择刚刚创建的项目文件夹 my-project来进行 Vue 开发

了解 Vue.js 核心概念

一. 组件(Components)

组件是 Vue.js 的核心概念之一,Vue 应用由组件构建而成。组件可以是小的功能单元,也可以是大型的应用结构。每个组件都有自己的 HTML 模板、样式和逻辑。

示例:

Vue.component('my-component', {
    template: '<p>这是一个组件!</p>'
});

二. 模板语法(Template Syntax)

Vue 使用一个简洁的模板语法,它允许你在 HTML 的标记中嵌入 JavaScript 表达式。Vue 的模板在内部被编译成虚拟 DOM 渲染。

<div id="app">
    <h1>{{ greeting }}</h1> <!-- 使用大括号绑定数据 -->
</div>

<script>
new Vue({
    el: '#app',
    data: {
        greeting: '欢迎使用 Vue.js!' // 绑定数据
    }
});
</script>

三. 数据绑定(Data Binding)

数据绑定(Data Binding)是 Vue.js 的一个核心概念,它允许你将 Vue 实例中的数据与 DOM 元素进行同步,构建动态的用户界面。通过数据绑定,Vue.js 实现了单向和双向数据绑定,使得开发变得更加简单和高效。以下是关于数据绑定的详细知识点:

1. 单向数据绑定

单向数据绑定是指数据流向 DOM,在 Vue 实例中定义的数据会被渲染到视图中。当视图中的数据改变时,它不会影响 Vue 实例内的数据。

示例

<div id="app">
    <p>{{ message }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script>
new Vue({
    el: '#app',
    data: {
        message: '欢迎使用 Vue.js!'
    }
});
</script>

在这个例子中,message 的值渲染到 <p> 标签中,内容会显示为 "欢迎使用 Vue.js!"。

2. 双向数据绑定

双向数据绑定允许你将 DOM 元素的值与 Vue 实例中的数据同步变化。这在表单控件(输入框、复选框、选择框等)中尤其常用。

双向数据绑定可以通过 v-model 指令来实现,方便与表单输入元素的交互。

主要用途v-model 是用于实现表单输入元素的双向数据绑定。例如,您可以将输入框中的值与 Vue 实例中的数据同步。

典型用法:常用于 input、textarea 和 select 元素。

示例:

<div id="app">
    <input v-model="inputValue" placeholder="输入内容"> <!-- 双向绑定 -->
    <p>你输入的内容是: {{ inputValue }}</p> <!-- 显示绑定内容 -->
</div>

<script>
new Vue({
    el: '#app',
    data: {
        inputValue: '' // 定义输入值
    }
});
</script>

3. 计算属性

计算属性是基于依赖的数据进行计算和缓存的属性,通常用于需要进行数据处理的场景。计算属性不是实时更新的,但会在依赖的数据变化时重新计算。

示例

<div id="app">
    <p>原文字串:{{ originalText }}</p>
    <p>反转后的字符串:{{ reversedText }}</p>
</div>

<script>
new Vue({
    el: '#app',
    data: {
        originalText: 'Hello Vue!'
    },
    computed: {
        reversedText() {
            return this.originalText.split('').reverse().join('');
        }
    }
});
</script>

4. 侦听器

侦听器可以监控 Vue 实例中的数据变化,并在数据变化时执行额外的代码。通常用于处理复杂或者开销较大的操作。

<div id="app">
    <input v-model="number" placeholder="输入一个数字">
    <p>平方:{{ square }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script>
new Vue({
    el: '#app',
    data: {
        number: 0
    },
    computed: {
        square() {
            return this.number * this.number; // 计算平方
        }
    },
    watch: {
        number(newValue) {
            console.log(`数字已变为:${newValue}`);
        }
    }
});
</script>
Vue 基础

用于动态绑定的指令

  • v-bind:用于动态绑定 HTML 属性
  • v-if、v-else-if、v-else:用于条件渲染
  • v-for:用于循环渲染列表
  • v-show:用于控制元素的显隐

v-bind:用于动态绑定 HTML 属性

典型用法:常用于设置非表单元素的属性,也可以用于样式与类的动态绑定。

1. 绑定 HTML 属性
使用 v-bind 指令可以将 Vue 数据属性的值绑定到 HTML 元素的属性上。例如,你可以用它来动态设置 hrefsrcclass 和 style 等 HTML 属性。

示例

<div id="app">
    <a v-bind:href="url">点击这里</a>
    <img v-bind:src="imageSrc" alt="动态图片">
</div>

<script>
new Vue({
    el: '#app',
    data: {
        url: 'https://www.example.com',
        imageSrc: 'https://www.example.com/image.jpg'
    }
});
</script>

在上面的示例中,href 属性和 src 属性的值都绑定到 Vue 实例中的数据属性。

简写方式

在 Vue 中,可以使用 : 作为 v-bind 的简写。上面的代码可以简化为:

<div id="app">
    <a :href="url">点击这里</a>
    <img :src="imageSrc" alt="动态图片">
</div>

2. 绑定 CSS 类

v-bind 也可以用于动态绑定 CSS 类。这在需要根据某些条件来更改样式时非常有用。

示例

<div id="app">
    <button :class="{ active: isActive }">点击我</button>
    <button @click="toggleActive">切换状态</button>
</div>

<script>
new Vue({
    el: '#app',
    data: {
        isActive: false // 初始情况下按钮不活跃
    },
    methods: {
        toggleActive() {
            this.isActive = !this.isActive; // 切换按钮活跃状态
        }
    }
});
</script>

<style>
.active {
    background-color: green; /* 设置活跃状态下的背景颜色 */
    color: white;
}
</style>

在这个例子中,按钮的类名会根据 isActive 的值来变化。点击按钮会切换 isActive 的值,从而修改按钮的样式。

Vue 基础

3. 绑定行内样式

v-bind 还可以用于绑定行内样式,允许你动态设置样式对象。

<div id="app">
    <div :style="{ color: textColor, fontSize: fontSize }">这是有动态样式的文本</div>
    <button @click="changeStyle">改变样式</button>
</div>

<script>
new Vue({
    el: '#app',
    data: {
        textColor: 'blue',
        fontSize: '20px'
    },
    methods: {
        changeStyle() {
            this.textColor = this.textColor === 'blue' ? 'red' : 'blue'; // 切换文本颜色
            this.fontSize = this.fontSize === '20px' ? '30px' : '20px'; // 切换文本大小
        }
    }
});
</script>

在这个示例中,文本的颜色和大小是动态的,并可以通过按钮点击进行切换。

v-if、v-else-if、v-else:用于条件渲染

1. v-if 的基本使用

v-if 指令用于根据某个条件来决定是否渲染一个元素或组件。如果条件为真,该元素将被渲染;如果条件为假,元素则不会出现在 DOM 中。

基本语法

<v-if="condition">{{ content }}</v-if>

这里的 condition 是一个表达式,当它的值为真时,内容 content 将被渲染。

2. 示例代码

下面是一个简单的示例,展示了如何使用 v-if 来控制一个段落的显示与隐藏:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue.js v-if 示例</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>

<body>
    <div id="app">
        <p v-if="isVisible">这个段落会根据 isVisible 的值显示或隐藏。</p>
        <button @click="toggleVisibility">切换可见性</button>
    </div>

    <script>
        new Vue({
            el: '#app',
            data: {
                isVisible: true // 控制段落的显示与隐藏
            },
            methods: {
                toggleVisibility() {
                    this.isVisible = !this.isVisible; // 切换 isVisible 的值
                }
            }
        });
    </script>
</body>

</html>

在这个示例中:

  • 当 isVisible 为 true 时,段落会被渲染。
  • 当用户点击按钮时,toggleVisibility 方法会切换 isVisible 的值,从而控制段落的显示和隐藏。

3. 多重 v-if 条件

你还可以在同一个元素中使用 v-else 和 v-else-if 来处理多个条件。

<p v-if="value === 1">Value is 1</p>
<p v-else-if="value === 2">Value is 2</p>
<p v-else>Value is neither 1 nor 2</p>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue.js v-if Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <!-- 引入 Vue.js -->
</head>
<body>
    <div id="app">
        <h1>条件渲染示例</h1>
        <input type="number" v-model.number="value" placeholder="输入一个数字"> <!-- 使用 .number 修饰符 -->
      
        <p v-if="value === 1">Value is 1</p>
        <p v-else-if="value === 2">Value is 2</p>
        <p v-else-if="value !== null">Value is neither 1 nor 2</p> <!-- 确保只有当 value 不是 null 时才显示这个 -->
        <p v-else>Please enter a value</p> <!-- 当没有输入值时 -->
    </div>

    <script>
        new Vue({
            el: '#app',
            data: {
                value: null // 初始化值为空
            }
        });
    </script>
</body>
</html>

在输入框中输入数字:

  • 输入 1,页面会显示 "Value is 1"。
  • 输入 2,页面会显示 "Value is 2"。
  • 输入其他数字,如 3,页面会显示 "Value is neither 1 nor 2"。
  • 如果不输入任何值,页面会显示 "Please enter a value"。

v-for:用于循环渲染列表

v-for 是 Vue.js 中用于循环渲染列表的指令。它用于将数组或对象中的数据动态渲染为多个 DOM 元素。

1. v-for 的基本用法

v-for="(item, index) in items"
  • item:代表当前循环的项(数组中的元素)。
  • index:可选参数,当前项的索引。
  • items:要进行循环的数据,可以是数组或对象。

2. 示例

下面是一个简单的使用 v-for 的示例,展示如何循环遍历一个数组并渲染列表项。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>v-for 示例</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="app">
        <h1>水果列表</h1>
        <ul>
            <li v-for="(fruit, index) in fruits" :key="index">
                {{ index + 1 }}. {{ fruit }}
            </li>
        </ul>
        <button @click="addFruit">添加水果</button>
    </div>

    <script>
        new Vue({
            el: '#app',
            data: {
                fruits: ['苹果', '香蕉', '橙子'] // 初始化水果数组
            },
            methods: {
                addFruit() {
                    this.fruits.push('新水果'); // 添加新水果
                }
            }
        });
    </script>
</body>
</html>

在这个示例中:

  • 创建了一个水果列表,使用 v-for 指令循环遍历 fruits 数组。
  • 在 <li> 内部,我们显示水果的索引和名称。
  • 使用 :key 属性进行列表项的唯一标识,建议始终提供这个属性以提高性能和避免异常。

3. 使用对象进行 v-for 循环

你也可以遍历对象的属性,使用以下语法:

v-for="(value, key) in object"

示例:

<div id="app">
    <h1>信息列表</h1>
    <ul>
        <li v-for="(value, key) in info" :key="key">
            {{ key }}: {{ value }}
        </li>
    </ul>
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            info: {
                姓名: '张三',
                年龄: 28,
                职业: '程序员'
            }
        }
    });
</script>
Vue 基础

4. 嵌套 v-for

v-for 可以嵌套在其他 v-for 中,用于处理多维数组。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>v-for 示例</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <!-- 引入 Vue.js -->
</head>
<body>
    <div id="app">
        <h1>分类列表</h1>
        <ul>
            <li v-for="(category, index) in categories" :key="index">
                <strong>{{ category.name }}</strong>
                <ul>
                    <li v-for="(item, itemIndex) in category.items" :key="itemIndex">
                        {{ item }}
                    </li>
                </ul>
            </li>
        </ul>
    </div>

    <script>
        new Vue({
            el: '#app',
            data: {
                categories: [
                    { name: '水果', items: ['苹果', '香蕉', '橙子'] },
                    { name: '蔬菜', items: ['胡萝卜', '西兰花'] }
                ]
            }
        });
    </script>
</body>
</html>
Vue 基础

注意事项

  • 使用 key 属性:当使用 v-for 渲染列表时,建议为每个列表项提供一个唯一的 key。这样可以优化性能,确保 Vue.js 能有效地跟踪元素,减少不必要的渲染。
  • 列表项的顺序:如果数据是可变的(如添加或删除项目),使用唯一的 key 属性可以让 Vue.js 正确识别每个元素,避免出现错误的顺序或状态。
  • 循环嵌套v-for 可以嵌套使用来处理复杂的数据结构,比如二维数组或对象,但要小心避免过多嵌套,使逻辑变得复杂。

Methods

基本概念

methods 是 Vue 实例的一个属性,用于定义要在组件中调用的函数。这些方法可以用于处理用户交互、事件,以及其他逻辑。

在 Vue 实例中,你可以通过 methods 属性定义多个方法,语法如下:

new Vue({
    el: '#app',
    data: {
        // 数据属性
    },
    methods: {
        methodName() {
            // 方法逻辑
        }
    }
});

1. 定义方法

methods: {
    increment() {
        this.count++; // 每次调用时增加 count 的值
    }
}

2. 绑定事件

使用 @ 或 v-on 指令将方法与 DOM 元素的事件绑定在一起。例如,你可以将点击事件与方法关联:

<button @click="increment">增加</button>

3. 访问数据

在 methods 中,可以通过 this 关键字访问 Vue 实例的数据属性:

methods: {
    greet() {
        alert(`你好,${this.name}!`); // 访问和使用 data 属性
    }
}

4. 方法参数

方法可以接收参数,你可以在模板中通过事件传递参数。例如:

methods: {
    showMessage(message) {
        alert(message); // 使用参数
    }
}

在模板中调用时:

<button @click="showMessage('欢迎使用 Vue!')">显示消息</button>

完整示例,展示 methods 的使用:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue.js methods 示例</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="app">
        <h1>{{ title }}</h1>
        <button @click="increment">增加</button>
        <p>当前计数:{{ count }}</p>
        <input v-model="message" placeholder="输入消息">
        <button @click="showMessage(message)">显示消息</button>
    </div>

    <script>
    new Vue({
        el: '#app',
        data: {
            title: '计数器',
            count: 0,
            message: ''
        },
        methods: {
            increment() {
                this.count++; // 增加计数
            },
            showMessage(msg) {
                alert(`你输入的消息是: ${msg}`); // 显示输入的消息
            }
        }
    });
    </script>
</body>
</html>
Vue 基础

Demo 练习:

在这个练习中,我们将创建一个简单的待办事项清单(To-Do List),并使用 Vue 来管理待办项的添加和删除。

<!DOCTYPE html>
<html>
<head>
    <title>待办事项清单</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <!-- 引入 Vue.js -->
</head>
<body>
    <div id="app">
        <h1>我的待办事项清单</h1>
        <input v-model="newTask" placeholder="添加新任务"> <!-- 输入框 -->
        <button @click="addTask">添加</button> <!-- 添加按钮 -->
        <ul>
            <li v-for="(task, index) in tasks" :key="index">
                {{ task }} <button @click="removeTask(index)">删除</button> <!-- 删除按钮 -->
            </li>
        </ul>
    </div>

    <script>
    new Vue({
        el: '#app', // 将 Vue 实例挂载到 id 为 app 的元素上
        data: {
            newTask: '', // 新任务的输入值
            tasks: [] // 存储任务的数组
        },
        methods: {
            addTask: function() {
                // 添加新任务的方法
                if (this.newTask.trim() !== '') { // 检查输入不为空
                    this.tasks.push(this.newTask.trim()); // 将新任务添加到任务数组中
                    this.newTask = ''; // 清空输入框
                }
            },
            removeTask: function(index) {
                // 删除任务的方法
                this.tasks.splice(index, 1); // 从任务数组中移除指定索引的任务
            }
        }
    });
    </script>
</body>
</html>
Vue 基础

思考:Vue 相比于原生 JS 代码到底有什么优势?

分别写出一个功能完整的 TodoList(待办事项)

1. 原生 JavaScript 版本(Vanilla JS)

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8" />
  <title>原生JS TodoList</title>
</head>
<body>

  <h2>我的待办事项(原生JS)</h2>
  <input type="text" id="input-task" placeholder="输入任务" />
  <button onclick="addTask()">添加</button>

  <ul id="task-list">
    <!-- 任务会动态插入到这里 -->
  </ul>

  <script>
    // 获取 DOM 元素
    const input = document.getElementById('input-task');
    const list = document.getElementById('task-list');

    // 初始任务列表
    let tasks = ['学习JavaScript', '写个Demo'];

    // 页面加载时渲染初始任务
    function renderTasks() {
      list.innerHTML = ''; // 清空
      tasks.forEach((task, index) => {
        const li = document.createElement('li');
        li.textContent = task;

        const btn = document.createElement('button');
        btn.textContent = '删除';
        btn.onclick = () => removeTask(index); // 删除对应任务

        li.appendChild(btn);
        list.appendChild(li);
      });
    }

    // 添加任务
    function addTask() {
      const value = input.value.trim();
      if (value) {
        tasks.push(value);
        input.value = '';
        renderTasks(); // 手动重新渲染
      }
    }

    // 删除任务
    function removeTask(index) {
      tasks.splice(index, 1);
      renderTasks(); // 手动重新渲染
    }

    // 初始化页面
    renderTasks();
  </script>

</body>
</html>

2. Vue3 版本(使用 CDN 快速体验)

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8" />
  <title>Vue TodoList</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>
<body>

  <div id="app">
    <h2>我的待办事项(Vue3)</h2>
    <input 
      v-model="newTask" 
      @keyup.enter="addTask"
      placeholder="输入任务"
    />
    <button @click="addTask">添加</button>

    <ul>
      <li v-for="(task, index) in tasks" :key="index">
        {{ task }}
        <button @click="removeTask(index)">删除</button>
      </li>
    </ul>
  </div>

  <script>
    Vue.createApp({
      data() {
        return {
          newTask: '',
          tasks: ['学习Vue', '写个Demo']
        };
      },
      methods: {
        addTask() {
          if (this.newTask.trim()) {
            this.tasks.push(this.newTask);
            this.newTask = '';
          }
        },
        removeTask(index) {
          this.tasks.splice(index, 1);
        }
      }
    }).mount('#app');
  </script>

</body>
</html>

对比分析:JS vs Vue

对比项原生 JavaScriptVue
代码量多(需手动操作 DOM)少(声明式模板)
数据管理tasks 数组 + 手动同步数据驱动,自动更新视图
添加/删除逻辑要 createElementappendChildremove()只改数据,视图自动变
事件绑定btn.onclick = ...模板中直接写 @click="..."
双向绑定手动取 input.valuev-model 自动同步
维护性难扩展,容易出错结构清晰,易复用

举个例子说明“数据驱动”

在 Vue 中:
this.tasks.push('新任务');  // 只改数据
// → 页面自动出现新任务,无需你操作 DOM!

而在原生 JS 中:
tasks.push('新任务');
renderTasks(); // 必须手动调用渲染函数

Vue 生命周期

Vue.js 的生命周期是指从创建一个 Vue 实例到销毁的整个过程。在这个生命周期的不同阶段,Vue 会调用一些特定的生命周期钩子函数,这些钩子函数允许开发者在特定时刻执行代码。生命周期钩子使得我们可以在 Vue 实例的不同状态下执行自定义操作,比如初始化数据、设置事件监听、清理资源等。

以下是 Vue 实例生命周期的主要阶段:

  1. 创建阶段
    • beforeCreate:实例初始化之后,数据观测和事件配置之前调用。
    • created:实例已创建完成,数据观测和事件配 置已完成,但尚未挂载到 DOM。
  2. 挂载阶段
    • beforeMount:在挂载开始之前被调用,相关的 render 函数首次调用。
    • mounted:实例被挂载后被调用,el 被替换为实例的 $el。此时可以访问 DOM。
  3. 更新阶段
    • beforeUpdate:数据更改,DOM 重新渲染之前调用。
    • updated:由于数据更改导致的重新渲染完成后调用。
  4. 销毁阶段
    • beforeDestroy:组件实例被销毁之前调用,此时可以进行清理操作。
    • destroyed:组件实例已被销毁后调用,完全可清理及销毁对象。
Vue 基础

以下是一个简单的 Vue 组件示例,展示了如何在生命周期钩子中执行代码。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 生命周期示例</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <!-- 确保引用了Vue.js -->
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f9f9f9;
            padding: 20px;
        }
        h1 {
            color: #333;
        }
    </style>
</head>
<body>

<div id="app">
    <h1>{{ message }}</h1>
</div>

<script>
new Vue({
    el: '#app',
    data: {
        message: 'Hello, Vue!'
    },
    beforeCreate() {
        console.log('beforeCreate: 实例刚初始化');
    },
    created() {
        console.log('created: 实例已创建');
    },
    beforeMount() {
        console.log('beforeMount: 即将挂载');
    },
    mounted() {
        console.log('mounted: 实例已挂载在 DOM 上');
    },
    beforeUpdate() {
        console.log('beforeUpdate: 数据即将更新');
    },
    updated() {
        console.log('updated: 数据更新完毕');
    },
    beforeDestroy() {
        console.log('beforeDestroy: 实例即将销毁');
    },
    destroyed() {
        console.log('destroyed: 实例已销毁');
    }
});
</script>

</body>
</html>
Vue 基础

通过生命周期钩子,开发者可以在 Vue 实例的不同阶段插入自定义逻辑。这对于初始化数据、绑定事件、处理异步请求、清除资源等操作都非常有用。掌握生命周期的各个阶段能够帮助你更好地控制组件的行为和状态,从而提高应用的性能和用户体验。

ES6 语法新特性

ES6(ECMAScript 2015)引入了一系列新的语法特性和改进,使得 JavaScript 在书写风格上更加简洁和现代化。以下是一些主要的 ES6 语法风格及其特点:

1. 块级作用域

let 和 const:引入了对变量声明的新语法,let 用于声明可变的变量,const 用于声明不可变的常量。

ES5 示例

在 ES5 中,变量声明总是使用 var,它的作用域是函数级的。

function example() {
    if (true) {
        var x = 10; // x 在函数作用域内有效
    }
    console.log(x); // 输出: 10
}

example();

对比 ES6
使用 let 或 const,以实现块级作用域。

function example() {
    if (true) {
        let y = 20; // y 在块级作用域内有效
        const z = 30; // z 在块级作用域内有效
        console.log(y); // 输出: 20
        console.log(z); // 输出: 30
    }
    // console.log(y); // 报错:y is not defined
}

example();

2. 箭头函数

更简洁的函数表示法,且不绑定自己的 this 值,使得在回调函数中使用 this 更加直观。

const add = (a, b) => a + b;

ES5 示例

使用传统的函数表达式。

var add = function(a, b) {
    return a + b;
};

var result = add(5, 10);
console.log(result); // 输出: 15

对比 ES6

使用箭头函数语法。

const add = (a, b) => a + b; // 更简洁的写法
const result = add(5, 10);
console.log(result); // 输出: 15

3. 模板字符串

使用反引号 ` 来包围字符串,可以轻松插入变量和进行多行字符串。

let name = '世界';
let greeting = `你好,${name}`; // 支持插值

ES5 示例

使用字符串连接来插入变量。

var name = '世界';
var greeting = '你好,' + name + '!'; // 字符串拼接
console.log(greeting); // 输出: 你好,世界!

对比 ES6

使用模板字符串进行插值。

let name = '世界';
let greeting = `你好,${name}!`; // 支持变量插值和多行
console.log(greeting); // 输出: 你好,世界!

4. 解构赋值

允许从数组或对象中提取值,语法更加简洁。

const arr = [1, 2, 3];
const [a, b] = arr; // 数组解构

const obj = { x: 1, y: 2 };
const { x, y } = obj; // 对象解构

ES5 示例

使用索引或属性赋值来获取数组或对象的值。

var arr = [1, 2, 3];
var a = arr[0];
var b = arr[1]; // 使用索引访问

var obj = { x: 1, y: 2 };
var x = obj.x;
var y = obj.y; // 使用属性访问

对比 ES6

使用解构赋值,减少代码量。

const arr = [1, 2, 3];
const [a, b] = arr; // 数组解构

const obj = { x: 1, y: 2 };
const { x, y } = obj; // 对象解构

5. 默认参数

函数参数可以设置默认值,有助于减少需要判断参数是否为空的代码。

function multiply(a, b = 1) {
    return a * b;
}

ES5 示例

需要提前检查参数是否为 undefined

function multiply(a, b) {
    b = typeof b !== 'undefined' ? b : 1; // 手动检查
    return a * b;
}

console.log(multiply(5)); // 输出: 5

对比 ES6

可以为参数设置默认值。

function multiply(a, b = 1) {
    return a * b;
}

console.log(multiply(5)); // 输出: 5

6. 扩展运算符

用于数组和对象的展开,能够简洁地合并多个数组或复制对象。

const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = [...arr1, ...arr2]; // 数组合并

const obj1 = { a: 1 };
const obj2 = { b: 2 };
const combinedObj = { ...obj1, ...obj2 }; // 对象合并

ES5 示例

使用 concat() 方法合并数组,或者循环通过 for 手动添加对象属性。

var arr1 = [1, 2];
var arr2 = [3, 4];
var combined = arr1.concat(arr2); // 数组合并

// 对象合并
var obj1 = { a: 1 };
var obj2 = { b: 2 };
var combinedObj = {};
for (var key in obj1) combinedObj[key] = obj1[key];
for (var key in obj2) combinedObj[key] = obj2[key];

对比 ES6

使用展开运算符(...)来简化这些操作。

const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = [...arr1, ...arr2]; // 数组合并

const obj1 = { a: 1 };
const obj2 = { b: 2 };
const combinedObj = { ...obj1, ...obj2 }; // 对象合并

7. 类与模块

  • 使用 class 语法定义类,使得面向对象编程的风格更加接近其他编程语言。
  • 引入模块化语法,使用 import 和 export 来管理代码的组织和依赖。
class Person {
    constructor(name) {
        this.name = name;
    }
    greet() {
        return `你好,${this.name}`;
    }
}

export default Person; // 导出

ES5 示例

使用构造函数和原型来实现面向对象编程。

function Person(name) {
    this.name = name;
}

Person.prototype.greet = function() {
    return '你好,' + this.name;
};

var person = new Person('张三');
console.log(person.greet()); // 输出: 你好,张三

对比 ES6

引入 class 语法。

class Person {
    constructor(name) {
        this.name = name;
    }
    greet() {
        return `你好,${this.name}`; // 使用模板字符串
    }
}

const person = new Person('张三');
console.log(person.greet()); // 输出: 你好,张三

8. Promise

引入 Promise 对象,使得处理异步操作更加直观,避免了回调地狱(callback hell)。

const myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功!');
    }, 1000);
});

ES5 示例

使用回调函数处理异步操作。

function asyncOperation(callback) {
    setTimeout(function() {
        callback('成功!'); // 调用回调
    }, 1000);
}

asyncOperation(function(result) {
    console.log(result); // 输出: 成功!
});

对比 ES6

使用 Promise 使得异步操作更加直观。

const myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功!'); // 直接调用 resolve
    }, 1000);
});

myPromise.then(result => {
    console.log(result); // 输出: 成功!
});

ES6 在语法上提供了更多方便的特性,使得代码更加简洁、可读性更强。它让开发者可以更方便地处理变量、函数、异步操作和对象。

Axios

基本概念

Vue 应用需要与后端进行 HTTP 请求来获取或发送数据,只能通过Axios

为什么学习 Axios

  1. HTTP 请求:
    • Axios 是一个基于 Promise 的 HTTP 客户端,能够简化与服务器的交互,支持发送 GET、POST、PUT、DELETE 等请求。
    • 现代应用通常需要获取远程数据或发送数据到服务器,掌握 Axios 将使你能够高效地进行这些操作。
  2. 处理请求和响应:
    • Axios 提供了易于使用的 API,可以配置请求头、参数、超时等,方便开发者根据需要调整请求。
    • 支持响应的拦截器,可以在数据到达应用之前进行处理,如错误处理、加载状态更新等。
  3. 简化异步操作:
    • Axios 使用 Promise,使得处理异步操作变得更加直观,不再需要嵌套的回调函数(回调地狱)。
    • 配合 async/await 使用时,能够让代码更加清晰可读。
  4. 跨浏览器支持:
    • Axios 兼容现代浏览器,并处理了一些常见的浏览器差异性问题(如 JSON 请求的序列化/反序列化)。

安装 Axios

在 Vue 项目中,你可以通过 npm 或 yarn 安装 Axios:

npm install axios
# 或者
yarn add axios

基本使用

Axios 提供了简单的 API 来发送 HTTP 请求。以下是一些常见的用法。

发送 GET 请求

axios.get('https://api.example.com/items')
    .then(response => {
        console.log(response.data); // 处理返回的数据
    })
    .catch(error => {
        console.error('请求错误:', error);
    });

发送 POST 请求

axios.post('https://api.example.com/items', {
    name: '新任务',
    completed: false
})
    .then(response => {
        console.log('任务添加成功:', response.data);
    })
    .catch(error => {
        console.error('添加任务失败:', error);
    });

Django 和 Vue.js前后端项目不分离

利用 Django 和 Vue.js 通过引用 CDN 方式,构建一个简单的待办事项清单 (To-Do List) ,包括如何使用 GET 和 POST 请求与 Django 后端进行数据库交互。

创建 Django 项目和应用

创建一个新的 Django 项目和应用。在这个示例中,项目名称为 DjangoProject,应用名称为 myapp

确保将 myapp 添加到 settings.py 中的 INSTALLED_APPS

# DjangoProject/settings.py

INSTALLED_APPS = [
    ...
    'myapp',
    'rest_framework',  # 确保 Django REST Framework 已安装
]

安装 Django REST Framework

Django REST Framework 是一个强大的网页 API 构建工具,具有序列化、视图集等功能。

pip install djangorestframework

创建待办事项模型

在 models.py 中定义 TodoItem 模型,存储任务和其完成状态。模型是 Django ORM 和数据库之间的连接。

在 myapp/models.py 文件中定义待办事项模型:

# myapp/models.py

from django.db import models

class TodoItem(models.Model):
    task = models.CharField(max_length=200)
    completed = models.BooleanField(default=False)

    def __str__(self):
        return self.task

可选择关联到 mysql 数据库(PyMySQL方式)

确保您在您的 Python 环境中安装了 PyMySQL。可以通过 pip 安装它:

pip install PyMySQL

配置 Django 设置

在您的 Django 项目的 settings.py 文件中,找到 DATABASES 设置,并进行如下配置(假设您已经创建了名为 mydatabase 的数据库):

# DjangoProject/settings.py

import os
import pymysql

# 使用 PyMySQL 作为 MySQL 的 DB API 适配器
pymysql.install_as_MySQLdb()

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myapp',  # 数据库名称
        'USER': 'root',      # 数据库用户名
        'PASSWORD': 'xxxxxxxx',  # 数据库用户密码
        'HOST': 'localhost',   # 数据库主机
        'PORT': '3306',        # 数据库端口,通常为 3306
    }
}

确保您已经在 MySQL 中创建了数据库

CREATE DATABASE myapp;

创建序列化器和视图

创建一个序列化器,用于将模型转换为 JSON 格式,并实现相应的 API 接口。序列化器负责将 Django 模型转换为 JSON 格式。处理 HTTP 请求并返回序列化数据。

myapp/serializers.py

# myapp/serializers.py

from rest_framework import serializers
from .models import TodoItem

class TodoItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = TodoItem
        fields = '__all__'

myapp/views.py

# myapp/views.py

from rest_framework import viewsets
from .models import TodoItem
from .serializers import TodoItemSerializer

class TodoItemViewSet(viewsets.ModelViewSet):
    queryset = TodoItem.objects.all()
    serializer_class = TodoItemSerializer

 配置 URL 路由

在 urls.py 中配置 API 路由和主页视图:

# DjangoProject/urls.py

from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from myapp.views import TodoItemViewSet
from django.views.generic import TemplateView

# 创建路由
router = DefaultRouter()
router.register(r'todos', TodoItemViewSet)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include(router.urls)),  # API 路由
    path('', TemplateView.as_view(template_name='index.html')),  # 主页视图
]

创建模板

在项目根目录下的 templates 目录创建一个 index.html 文件。

<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>待办事项</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <style>
    body { font-family: Arial, sans-serif; padding:16px; }
    ul { padding-left:0; list-style:none; }
    li { margin:8px 0; display:flex; align-items:center; gap:8px; }
    .completed { text-decoration:line-through; color:#999; }
  </style>
</head>
<body>
  <div id="app">
    <h1>待办事项</h1>

    <input v-model="newTask" @keyup.enter="addTodo" placeholder="添加新任务" />
    <button @click="addTodo">添加</button>

    <ul>
      <li v-for="todo in todos" :key="todo.id">
        <input type="checkbox" :checked="todo.completed" @change="toggleCompleted(todo)" />
        <span :class="{ completed: todo.completed }" v-text="todo.task"></span>
        <button @click="deleteTodo(todo.id)">删除</button>
      </li>
    </ul>
  </div>

  <script>
    new Vue({
      el: '#app',
      data() {
        return { newTask: '', todos: [] };
      },
      mounted() { this.fetchTodos(); },
      methods: {
        fetchTodos() {
          axios.get('/api/todos/')
            .then(res => { this.todos = res.data || []; })
            .catch(err => { console.error('GET 失败', err); });
        },
        addTodo() {
          const text = (this.newTask || '').trim();
          if (!text) return;
          axios.post('/api/todos/', { task: text })
            .then(res => { this.todos.push(res.data); this.newTask = ''; })
            .catch(err => { console.error('POST 失败', err); });
        },
        deleteTodo(id) {
          axios.delete(`/api/todos/${id}/`)
            .then(() => { this.todos = this.todos.filter(t => t.id !== id); })
            .catch(err => { console.error('DELETE 失败', err); });
        },
        toggleCompleted(todo) {
          const newVal = !todo.completed;
          // 乐观更新
          todo.completed = newVal;
          axios.patch(`/api/todos/${todo.id}/`, { completed: newVal })
            .catch(err => {
              // 回退
              todo.completed = !newVal;
              console.error('PATCH 失败', err);
            });
        }
      }
    });
  </script>
</body>
</html>

在这个 index.html 文件中:

  • 我们引入了 Vue.js 和 Axios 的 CDN。
  • 实现了一个可以添加新待办事项,删除已存在待办事项的简单接口。
  • 在 mounted 生命周期钩子中,调用 fetchTodos 方法以获取待办事项。
  • fetchTodos 使用 GET 请求从后端获取待办事项列表,并将结果存储在 todos 的数组中。
  • addTodo 方法通过 POST 请求将新任务添加到数据库,并更新本地数组。
  • deleteTodo 方法通过 DELETE 请求删除任务。

启动 Django 服务器

确保你已经进行了数据库迁移:

python manage.py makemigrations
python manage.py migrate

启动 Django 开发服务器:

python manage.py runserver

访问应用

在浏览器中访问 http://127.0.0.1:8000/,你就会看到待办事项清单应用。你可以添加新的待办事项,勾选完成状态,或删除已经添加的任务。

Vue 基础

http://127.0.0.1:8000/api/todos/

Vue 基础

数据库

Vue 基础

发布者:LJH,转发请注明出处:https://www.ljh.cool/43809.html

Like (0)
LJH的头像LJH
Previous 2025年8月27日 下午3:14
Next 2024年12月15日 下午11:44

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注