Vue.js

Vue.js第1课-起步

2019-05-09  本文已影响47人  e20a12f8855d

一、Vue.js 实现 HelloWorld

先来看一个简单地用 Vue.js 实现的 HelloWorld 例子:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>HelloWorld</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>

    <div id="app">{{msg}}</div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                msg: 'Hello World!'
            }
        });
        console.log(app); // wn {_uid: 0, _isVue: true, $options: {…}, _renderProxy: wn, _self: wn, …}
        console.log(app.$el); // <div id="app">Hello World!</div>
        console.log(app.$data); // {__ob__: we}
        console.log(app.$data.msg); // Hello World!

        setTimeout(function () {
            app.$data.msg = 'Bye!'
        }, 2000);
    </script>

</body>

</html>

通过控制台的几条打印数据及页面的渲染,可以看到,通过“实例.$属性”可以查询或改变数据。

下面的例子我将不再粘贴完整的 HTML 结构了,只放主要的逻辑代码到笔记中。

二、Vue.js 实现 TodoList

<div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="btnClick">添加</button>
    <ul>
        <li v-for="item in list">{{item}}</li>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            list: [],
            inputValue: ''
        },
        methods: {
            btnClick: function () {
                console.log(this.inputValue);
                this.list.push(this.inputValue);
                this.inputValue = '';
            }
        }
    });
</script>

上面代码中,给 input 绑定一个 v-model 指令,值和 data 中的 inputValue 关联,然后通过 v-on 给 button 绑定一个 click 事件 “btnClick”,事件写到实例的 methods 中,在该事件中,通过 this 可以获取到当前实例的属性和值,实现向 data 中 list 数组里添加 inputVlaue 的值。最后通过 v-for 指令,将 list 数组中的值循环渲染到页面上。

三、jQuery 实现 TodoList

下面通过 jQuery 使用面向对象编写来实现 TodoList:

<script src='https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js'></script>
<div>
    <input id="ipt" type="text">
    <button id="btn">添加</button>
    <ul id="ul"></ul>
</div>
<script>
    // jQuery TodoList  MVP 设计模式
    // 使用面向对象编写
    // 创建一个构造函数
    function Page() {};
    // 通过 $.extend 方法在 Page 的 prototype 上增加一些方法
    $.extend(Page.prototype, {
        // 初始化方法
        init: function () {
            this.bindEvents();
        },
        // 绑定事件
        bindEvents: function () {
            var btn = $("#btn");
            btn.on('click', $.proxy(this.handleBtnClick, this));
        },
        handleBtnClick: function () {
            var ipt = $("#ipt");
            var iptVal = ipt.val(); // 输入的值
            var ul = $("#ul");
            ul.append("<li>" + iptVal + "</li>");
            ipt.val("");
            console.log(iptVal);
        }
    });
    // 创建一个实例
    var page = new Page();
    page.init();
</script>

该方法和 Vue.js 实现的效果是一样的。

四、组建化修改 TodoList

1、全局组件的使用

创建一个全局组件 TodoList,如果组件的名称是驼峰命名法,那么在调用该组件时需要将大写改为小写,中间用“-”连接:

<div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="btnClick">添加</button>
    <ul>
        <!-- <li v-for="item in list">{{item}}</li> -->
        <todo-list v-bind:content="item" v-for="item in list"></todo-list>
    </ul>
</div>
<script>
    Vue.component('TodoList',{
        props: ['content'],
        template : '<li>{{content}}</li>'
    });
    var app = new Vue({
        el: '#app',
        data: {
            list: [],
            inputValue: ''
        },
        methods: {
            btnClick: function () {
                console.log(this.inputValue);
                this.list.push(this.inputValue);
                this.inputValue = '';
            }
        }
    });
</script>

补充:v-bind 给 HTML 标签设置属性。

2、局部组件的使用

先创建一个局部变量 TodoList,然后注册一个局部组件,把 TodoList 注册到 vue 事例中:

<div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="btnClick">添加</button>
    <ul>
        <!-- <li v-for="item in list">{{item}}</li> -->
        <todo-list v-bind:content="item" v-for="item in list"></todo-list>
    </ul>
</div>
<script>
    // 创建一个局部变量 TodoList
    var TodoList = {
        props: ['content'],
        template: '<li>{{content}}</li>'
    };

    var app = new Vue({
        el: '#app',
        // 注册一个局部组件,把 TodoList 注册到 vue 事例中
        components: {
            TodoList: TodoList
        },
        data: {
            list: [],
            inputValue: ''
        },
        methods: {
            btnClick: function () {
                console.log(this.inputValue);
                this.list.push(this.inputValue);
                this.inputValue = '';
            }
        }
    });
</script>

该方式和全局组件实现的效果一样。

五、组件间传值

在 TodoList 的基础上,我们想实现这样一个功能,点击当前元素,当前元素就被删除的效果。

先来思考一下如何给每一个子组件都添加一个点击事件?我们把事件方法写到父组件的 methods 中,此时点击子组件,会发现根本触发不了,是因为子组件的事件方法要写在子组件里,所以我们把事件方法放到子组件中的 methods 试一下:

<div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="btnClick">添加</button>
    <ul>
        <todo-list v-bind:content="item" v-for="item in list" @click="childClickFun">
        </todo-list>
    </ul>
</div>
<script>
    var TodoList = {
        props: ['content'],
        template: "<li>{{content}}</li>",
        methods: {
            childClickFun: function () {
                console.loh("child");
            }
        }
    };
    var app = new Vue({
        el: '#app',
        components: {
            TodoList: TodoList
        },
        data: {
            list: [],
            inputValue: ''
        },
        methods: {
            btnClick: function () {
                this.list.push(this.inputValue);
                this.inputValue = '';
            }
        }
    });
</script>

打开页面,点击子组件,发现有报错:“childClickFun” 没有在实例上定义,而是在呈现期间引用。

所以子组件的方法应该写在子组件的 methods 中,父组件的方法就应该写到父组件中。我们知道,父组件向子组件通过 props 传值,那子组件如何向父组件传值呢?子组件可以通过 $emit() 向父组件传值,我们来试一下:

<div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="btnClick">添加</button>
    <ul>
        <todo-list v-bind:content="item" v-bind:index="index" v-for="(item,index) in list" @click="clickFun">
        </todo-list>
    </ul>
</div>
<script>
    var TodoList = {
        props: ['content', 'index'],
        template: "<li @click='childClickFun'>{{content}}</li>",
        methods: {
            childClickFun: function () {
                this.$emit("click", this.index);
            }
        }
    };
    var app = new Vue({
        el: '#app',
        components: {
            TodoList: TodoList
        },
        data: {
            list: [],
            inputValue: ''
        },
        methods: {
            btnClick: function () {
                this.list.push(this.inputValue);
                this.inputValue = '';
            },
            clickFun: function (index) {
                console.log(index);
            }
        }
    });
</script>

上面代码,我在子组件中定义了一个 childClickFun,在父组件中定义了一个 clickFun。我们先给子组件 todo-list 设置一个属性 index,这个 index 是在 v-for 循环中添加的一个循环项,这样设置完成后,还需要在子组件中通过 props 接收一下。接着在子组件的 childClickFun 中通过 emit() 向外触发事件,这个 emit() 中第一个参数传递触发的事件,第二个参数点击的位置,也就是 this.index,然后在子组件的 template 中添加这个点击事件(注意:emit() 中传入的事件名称要和 template 中 @ 后面的名称一致,可以设置其他名字)。最后我们在父组件的 clickFun 中传一个参数 index,这个 index 就是当前点击的元素的位置,我们打开页面看一下:

现在弄明白了父子组件之间的传值问题,就可以实现最初我们想要实现的那个点击当前元素删除的功能了。

<div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="btnClick">添加</button>
    <ul>
        <todo-list v-bind:content="item" v-bind:index="index" v-for="(item,index) in list"
            @delete="handleItemDelete">
        </todo-list>
    </ul>
</div>
<script>
    var TodoList = {
        props: ['content', 'index'],
        template: "<li v-on:click='handleItemClick'>{{content}}</li>",
        methods: {
            handleItemClick: function () {
                // 子组件向父组件传值 $emit,向外触发事件
                // 第二个参数作为点击的位置
                this.$emit("delete", this.index);
            }
        }
    };

    // 父组件
    var app = new Vue({
        el: '#app',
        components: {
            TodoList: TodoList
        },
        data: {
            list: [],
            inputValue: ''
        },
        methods: {
            btnClick: function () {
                this.list.push(this.inputValue);
                this.inputValue = '';
            },
            handleItemDelete: function (index) {
                console.log(this.list)
                this.list.splice(index, 1);
            }
        }
    });
</script>

附上该系列文章代码地址 Vue.js_Learning

上一篇 下一篇

猜你喜欢

热点阅读