# vue 的引用

通过 script 标签的方式进行引用。

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

# 组件

vue 的核心功能之一就是组件

components

# 组件基本分类

  • 根组件
  • 可复用的功能组件

# 根组件的创建

通过 vue 提供的构造函数可以实例化出来一个跟组件实例对象

let app = new Vue(options);

应用最顶层的组件,一般情况下,一个独立的应用有且只有一个根组件(节点)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./js/vue.js"></script>
</head>
<body>
    <!-- VUE 的入口 -->
    <div id="app"></div>
    <script>
        // 创建一个根组件
        let app = new Vue({
            // 定义一个模板
            template: '<div>xiaokang.me</div>'
        })
        // 将模板添加到 #app 这个元素中
        app.$mount('#app')
    </script>
</body>
</html>

image-20200925182627376

上面发生了什么?

其实通过实例化 Vue 对象,传入配置字段 template 相当于定义了一个模板,通过 Vue 对象提供的 $mount 方法,将其添加到指定的标签元素中。类似于 createElementappendChild 的概念。

# 可复用的功能组件

通过 Vue 提供的静态方法 component 窗口可复用的功能组件

let component1 = Vue.component(options)

组件配置选项:https://cn.vuejs.org/v2/api/

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- VUE 的入口 -->
    <div id="app"></div>
    <script src="./js/vue.js"></script>
    <script>
        // 定义一个可以复用的组件
        Vue.component('tab', {
            template: `<div>这是一个tab选项卡</div>`
        })
        // 创建一个根组件
        let app = new Vue({
            // 定义一个模板
            template: `
            <div>
                <p>xiaokang.me</p> 
                <tab />
                <br />
            </div>
            `
        })
        app.$mount('#app')
    </script>
</body>
</html>

image-20200925191124804

# el 选项

如果提供了 el,且又没有提供 template,那么会自动把 el 的 innerHTML 作为 template。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- VUE 的入口 -->
    <div id="app">
        <h1>xiaokang.me</h1>
        <tab>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        // 定义一个可以复用的组件
        Vue.component('tab', {
            template: `<div>这是一个tab选项卡</div>`
        })
        // 创建一个根组件
        let app = new Vue({
            el: '#app'
        })
    </script>
</body>
</html>

image-20200925191629284

# data 与更新

使用 vue 的原因,在于数据,页面会根据不同的数据显示不同的内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- VUE 的入口 -->
    <!-- vue 中的花括号内可填入的内容
     * 表达式:可以通过运算(执行)得到结果(数据)的公式
     *  - 变量
     *  - 函数调用
     *  - 数学运算
     *
     * 语句:if,else,while,for....
     *
     * 数据来源于组件内部,比如 data 中的数据
     * 解析过程中,会自动绑定组件实例中的数据
     -->
    <div id="app">
        <h1>xiaokang.me</h1>
        <h2>name:</h2>
        <tab>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        // 定义一个可以复用的组件
        Vue.component('tab', {
            template: `<div>这是一个tab选项卡</div>`
        })
        // 创建一个根组件
        let app = new Vue({
            el: '#app',
            // 用来挂载组件所需要渲染的数据
            data: {
                name: 'Xioakang',
                age: 18
            }
        })
    </script>
</body>
</html>

将数据传入到 Vue 对象选项中的 data 字段,在模板里只需要通过 {{}}`即可调用到该属性,例如`{{name}} 表示调用 data.name ,其数据来源于 data 中的数据,所以不需要写 data.name

Vue 会把 data 传入的属性挂载到 Vue 对象中,因此属性命名时不可以与原有属性冲突。

image-20200925192227986

关于数据的更新,只需要改动属性即可。如图:

image-20200925192509124

# 拦截数据

简单来说,就是数据修改时拦截数据,这样就实现了只关注数据的修改,而不关心渲染。

vue3 之前,数据的监听是通过 Object.defineProperty 方法来实现的,但是该方法只能监听拦截单个数据,对于对象新增属性无法监听拦截。所以,对于数据对象中新增的属性,我们需要调用 vue 提供的方法来进行处理

对 vue 的模拟如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        let obj1 = {
            x: 1,
            y: 2
        }
        function render() {
            console.log('渲染了!');
        }
        let obj2 = Object.assign({}, obj1)
        // 当每次修改 x 属性时,调用 render 函数进行渲染。
        Object.defineProperty(obj1, 'x', {
            set(newVal) {
                // 如果使用 obj1 会导致循环递归的问题,因此使用另一个变量
                obj2.x = newVal
                render()
            },
            get() {
                return obj2.x
            }
        })
        obj1.x = 2
        console.log(obj1.x);
    </script>
</body>
</html>

acd5884e-83cb-40ec-a7e7-6038681601c5

通过 Object.defineProperty 监听拦截中存在一些问题

  • 属性新增属性
  • 数组方法:push、pop、shift、unshift、splice、sort、reverse
  • 数组新增值:[]
  • 数组 length 属性

以上的操作中并不会触发监听拦截

vue 对数组中的 pushpop 等方法进行重新包装,所以在 vue 中调用这些方法,可以对数组的修改进行监听拦截

https://cn.vuejs.org/v2/guide/list.html#%E5%8F%98%E5%BC%82%E6%96%B9%E6%B3%95-mutation-method

为了解决上述问题,vue2 提供了 set 方法,其原理如下:

function set(key, value) {
    Object.defineProperty(obj1, key, {
        set(newVal) {
            value = newVal;
            render();
        },
        get() {
            return value;
        }
    })
}

此时通过调用 set 方法即可对新属性进行拦截。

2f273461-26c0-46a3-8093-27d9cd0733cc

在 vue 中有两种方式调用 set 方法:

Vue.set(app.user, 'age', 19)
// 或下面的方法(app 为 Vue 的实例对象)
app.$set(app.user, 'age', 19)

e0bfbd08-c4de-4e91-a1d7-fa522f4b6cd7

更新于

请我喝[茶]~( ̄▽ ̄)~*

Dreamy.TZK 微信支付

微信支付

Dreamy.TZK 支付宝

支付宝