前言

对不起,我学习晚了。

前端迭代真是太快了,我所掌握的前端知识还停留在jQuery时期,这不正好就需要恶补一下前端新知识了,选择太多了,我决定直接从vue入手,把Nodejs、HTML5、CSS3、ES6都能带入进来学习,触类旁通。话不多说,正式进入vue学习入门第一课。

vue入门

页面源码直接在线打开:《vue框架学习入门demo》

1. 声明式渲染

<h3>入门</h3>
<div id="app">{{message}}</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: "Hello Vue!"
        }
    });
</script>

这是官方文档给出的第一个例子,看起来很简单吧,我们可以从这个例子发散一下思维,如果是jQuery怎么写呢。

<div id="jq_app"></div>
<script>
    var jqApp = {message: "Hello jQuery!"};
    jQuery('#jq_app').text(jqApp.message);
</script>

看起来渲染效果是一样的,但是vue版的渲染会随着 app.message 值的改变而自动更改渲染值,jQuery的这个渲染不会随着 jqApp.message 值的改变而更改渲染值,除非写出更复杂的代码才能达到同样效果。

有什么好处呢,好处就是如果我从接口请求了数据渲染这个值,当重新请求数据需要重新渲染时,vue版只需要执行 app.message="new value" 即可,不必去操作DOM修改值,vue会自动重新渲染。

单个值可能看不出优势,如果是下面这样的一整块需要渲染,那么就体现出优势了。

<div id="article">
    <h1 class="title">{{title}}</h1>
    <div><span class="author">{{author}}</span><span class="pub_time">{{publish_at}}</span></div>
    <div class="content">{{content}}</div>
</div>

jQuery来写上面这段渲染会很复杂,vue只需要维护几个字段就好了。

2. 绑定元素 attribute

<div id="app_2">
    <span v-bind:title="message">
        鼠标悬停几秒钟查看此处动态绑定的提示信息!
    </span>
</div>
<script>
    var app2 = new Vue({
        el: "#app_2",
        data: {
            message: '页面加载于 ' + new Date().toLocaleString()
        }
    });
</script>

这个例子学到了 v-bind:xxx="yyy" 这种语法,我把例子稍微延伸一下,应该也是可以运行吧。

<div id="app_2">
    <span v-bind:title="message" v-bind:style="styleInfo">
        鼠标悬停几秒钟查看此处动态绑定的提示信息!
    </span>
</div>
<script>
    var app2 = new Vue({
        el: "#app_2",
        data: {
            message: '页面加载于 ' + new Date().toLocaleString(),
            styleInfo: "color:red;"
        }
    });
</script>

内联样式属性 style 也可以绑定成功,说明理解得不错。

3. 条件

<div id="app_3">
    <p v-if="seen">现在你看到我了</p>
</div>
<script>
    var app3 = new Vue({
        el: '#app_3',
        data: {
            seen: true
        }
    });
</script>

上面是官方的例子,我在此基础上加了个切换按钮,代码如下。

<div id="app_3">
    <p><input type="button" class="button" value="显示/隐藏"></p>
    <p v-if="seen">现在你看到我了</p>
</div>
<script>
    var app3 = new Vue({
        el: '#app_3',
        data: {
            seen: true
        }
    });

    var ele3 = document.querySelector('#app_3');
    var btn3 = ele3.getElementsByClassName('button');
    btn3[0].addEventListener('click', function(){
        if (app3.seen) {
            app3.seen = false;
        } else {
            app3.seen = true;
        }
    });
</script>

这个绑定事件是我在不了解vue绑定事件怎么用的情况下,用原生js写的,vue里面有更好的封装,下面会有例子。

jQuery版估计得这么写:

<div id="jq_app_3">
    <p><input type="button" class="button" value="显示/隐藏(jq)"></p>
    <p class="seen-con">现在你看到我了</p>
</div>
<script>
    var jqApp3 = {seen: true};
    jQuery('#jq_app_3 > p > input[type=button]').on('click', function(){
        if (jqApp3.seen) {
            jQuery('#jq_app_3 .seen-con').hide();
            jqApp3.seen = false;
        } else {
            jQuery('#jq_app_3 .seen-con').show();
            jqApp3.seen = true;
        }
    });
</script>

4. 循环

<div id="app_4">
    <ol>
        <li v-for="todo in todos">
            {{todo.text}}
        </li>
    </ol>
</div>
<script>
    var app4 = new Vue({
        el: "#app_4",
        data: {
            todos: [
                {text: "学习JavaScript"},
                {text: "学习Vue"},
                {text: "整个牛项目"}
            ]
        }
    });
</script>

上面是官方的例子,我在此基础上加了个数据新增功能,代码如下。

<div id="app_4">
    <p><input type="text" class="text"><input type="button" class="button" value="增加"></p>
    <ol>
        <li v-for="todo in todos">
            {{todo.text}}
        </li>
    </ol>
</div>
<script>
    var app4 = new Vue({
        el: "#app_4",
        data: {
            todos: [
                {text: "学习JavaScript"},
                {text: "学习Vue"},
                {text: "整个牛项目"}
            ]
        }
    });

    var ele4 = document.querySelector('#app_4');
    var btn4 = ele4.getElementsByClassName('button');
    var txt4 = ele4.getElementsByClassName('text');

    btn4[0].addEventListener('click', function(){
        let con = txt4[0].value;
        if (con) {
            app4.todos.push({text: con});
            txt4[0].value = ''; // 清空文本框的值
            txt4[0].focus(); // 文本框继续获得输入焦点
        }
    });
</script>

这样就可以给这个列表添加项目了,比官方例子生动多了嘛。

至于jQuery版实现,算了,我不想写了...(PS:源码在demo里)

5. 绑定事件

<div id="app_5">
    <p>{{ message }}</p>
    <button v-on:click="reverseMessage">反转消息</button>
</div>
<script>
    var app5 = new Vue({
        el: "#app_5",
        data: {
            message: "hello Vue.js!"
        },
        methods: {
            reverseMessage: function() {
                this.message = this.message.split('').reverse().join('');
            }
        }
    });
</script>

原来vue绑定事件的语法是: v-on:event="eventMethod" ,缺失封装得挺好的哈。

6. 表单双向绑定

<div id="app_6">
    <p>{{ message }}</p>
    <input v-model="message" class="text">
</div>
<script>
    var app6 = new Vue({
        el: "#app_6",
        data: {
            message: "Hello Vue"
        }
    });
</script>

双向绑定也很简洁嘛,总算不用写jQuery那种事件监听了。

7. 组件

<div id="app_7">
    <ol>
        <todo-item v-for="item in groceryList" v-bind:todo="item" v-bind:key="item.id"></todo-item>
    </ol>
</div>
<script>
    // 在Vue中注册组件
    Vue.component('todo-item', {
        props: ['todo'],
        template: '<li>{{ todo.text }}</li>'
    });

    var app7 = new Vue({
        el: '#app_7',
        data: {
            groceryList: [
                {id: 0, text: '蔬菜'},
                {id: 1, text: '水果'},
                {id: 2, text: '牛肉'},
            ]
        }
    });
</script>

唔,组件的例子,初次看还听复杂的,看懂以后稍微联想一下,就想到了这个就是模版渲染了,为了保持html兼容性,自定义了html标签嘛。看懂就好,先不深究,在实际开发中再去一一应证。

8. 侦听器

<div id="watch-example">
    <p>问一个是或否(yes/no)的问题: <input v-model="question"></p>
    <p>{{ answer }}</p>
</div>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
<script>
    var watchExampleVM = new Vue({
        el: '#watch-example',
        data: {
            question: '',
            answer: '请先输入问题!'
        },
        watch: {
            // 如果 `question` 发生改变,这个函数就会运行
            question: function(newQuestion, oldQuestion) {
                this.answer = '正在输入中...';
                this.debouncedGetAnswer();
            }
        },
        // Vue实例初始化以后会执行这个函数
        // _.debounce()是lodash库提供的延迟执行函数
        created: function() {
            this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
        },
        methods: {
            getAnswer: function() {
                if (this.question.indexOf('?') === -1) {
                    this.answer = '问题要以问号结尾嘛 :-)'
                    return
                }
                this.answer = '思考一下...';
                var vm = this;
                axios.get('https://yesno.wtf/api')
                    .then(function(response) {
                        vm.answer = _.capitalize(response.data.answer)
                    })
                    .catch(function(error) {
                        vm.answer = 'Error! Could not reach the API. ' + error 
                    });
            }
        }
    });
</script>

Vue 生命周期图示见官网图片点这里

lodash 库的功能嘛,大概就是一些实用函数封装,不需要立马学习,使用时去lodash官网查一下,有时间也可以把其中的函数都看一遍,留个印象。

axios 库就是一个Ajax库了,和jQuery里的jQuery.ajax()类似,也算工具库,有时间可以封装了哪些东西。

总结

至此,对 vue 有了初步了解,学到了几个vue的语法。

v-bind:xxx="yyy" 绑定元素 attribute
v-if="xxx" 条件语句
v-for="item in list" 循环语句
v-on:xxx="yyy" 绑定事件
v-model="xxx" 表单元素双向绑定语法

这几种是模版引擎里常用的语法,vue实现得都很优雅,甚是喜欢。

--End--