Vue简单入门

104 阅读3分钟

上篇文章我们学了 uni-app 的简单入门,uni-app 是一个使用 Vue.js 开发所有前端应用的框架,这节我们来学习一下如何使用 vue 。

Vue简介

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

Vue使用体验

双向绑定

双向绑定

  • jquery 写法
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js" />
</head>
<body>
<input type="text" data-bind-0=name/>
<span data-bind-0="name"></span>
<script type="text/javascript">
    function DataBinder(object_id) {
        var pubSub = jQuery({});
        var data_attr = "bind-" + object_id,
            message = object_id + ":change";
        jQuery(document).on("change", "[data-" + data_attr + "]", function (evt) {
            var $input = jQuery(this);
            pubSub.trigger(message, [$input.attr("data-" + data_attr), $input.val()]);
        });
        pubSub.on(message, function (evt, prop_name, new_val) {
            jQuery("[data-" + data_attr + "=" + prop_name + "]").each(function () {
                var $bound = jQuery(this);
                if ($bound.is("input,textarea,select")) {
                    $bound.val(new_val);
                } else {
                    $bound.html(new_val);
                }
            });
        });
        return pubSub;
    }

    function User(uid) {
        var binder = new DataBinder(uid),
            user = {
                attributes: {},
                set: function (attr_name, val) {
                    this.attributes[attr_name] = val;
                    binder.trigger(uid + ":change", [attr_name, val, this]);
                },

                get: function (attr_name) {
                    return this.attributes[attr_name];
                },
                _binder: binder
            };

        return user;
    }

    var user = new User(0);
    user.set("name", "text");

</script>
</body>
</html>
  • Vue 写法
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
     <!--引入vue.js-->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <!--双向绑定-->
    <div id="app-1">
        <p>{{ msg }}</p>
        <input type="text" v-model="msg"/>
    </div>

</body>

<script>
    var app = new Vue({
        el: "#app-1",
        data: {
            msg: "时刻在奔跑"
        }
    })
</script>

</html>

从这里例子可以看出,Vue写法非常简洁,便利。

条件表达式

条件判断

代码如下所示

<body>
    <!--条件与循环-->
    <div id="app-if">
        <!--继续在控制台输入 appIf.seen = false,你会发现之前显示的消息消失了。-->
        <p v-if="seen">看到我了吗</p>
        <button @click="hidden">点下{{msg}}</button>
    </div>
</body>

<script>
    new Vue({
        el:"#app-if",
        data:{
            seen:true,
            msg:'隐藏'
        },
        methods:{
            hidden(){
                this.seen = false;
                this.msg= '显示';
            }
        }
    })
</script>

for循环

image-20210415230814980

<body>
    <div id="app">
        <ol>
            <li v-for="city in citys">
                {{city.name}}
            </li>
        </ol>
    </div>
</body>

<script>
    new Vue({
        el:"#app",
        data:{
            citys:[
                {name:"合肥市"},
                {name:"铜陵市"},
                {name:"安庆市"}
            ]
        }
    })
</script>

渲染Html

时刻在奔跑

<body>
    <div id="app">
        <p>html内容: {{ rawHtml }}</p>
        <p>html显示: <span v-html="rawHtml"></span></p>
    </div>
</body>

<!--双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令:-->
<script>
    new Vue({
        el:"#app",
        data: {
            rawHtml: "<a href='#'>时刻在奔跑</a> <img src='https://i.loli.net/2021/04/15/3jHaiZg4fUneRQT.gif' />"
        }
    })
</script>

Html 属性绑定

html属性

<body>
    <div id="app">
        <input type="text" v-model="userName" />
        <!--对于布尔 attribute (它们只要存在就意味着值为 true),v-bind 工作起来略有不同,在这个例子中:-->
        <button v-bind:disabled="isButtonDisabled" v-on:click="submit">提交</button>
        <!--如果 isButtonDisabled 的值是 null、undefined 或 false,则 disabled attribute 甚至不会被包含在渲染出来的 <button> 元素中。-->
    </div>
</body>

<!--Attribute
 Mustache 语法不能作用在 HTML attribute 上,遇到这种情况应该使用 v-bind 指令:-->
<script>
    new Vue({
        el:"#app",
        data: {
            userName:"",
            isButtonDisabled:false
        },
        methods:{
          submit(){
           var _this = this;
           alert("userName="+_this.userName);
           // 提交按钮禁用
           _this.isButtonDisabled = true;
           // 提交等待后台数据响应
          setTimeout(function (){
            // 提交完成之后,提交按钮放开
            alert("提交成功");
            _this.isButtonDisabled = false;
          }, 3000);
          }
        }
    })
</script>

JavaScript 表达式

image-20210416064558206

<body>
<div id="app">
    <div v-bind:id="'list-' + id"></div>
    <div v-bind:hidden="ok?true:false">显示出来</div>
    <p><span>1+1=</span>{{number+1}}</p>
    <div><span>are you ok ? {{ ok ? 'yes':'no'}}</span></div>
    <div>{{message.split('').reverse().join('')}}</div>
</div>

</body>

<!--实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
-->
<script>
    new Vue({
        el:"#app",
        data: {
            id: 1,
            number:1,
            ok:true,
            message:"abcd",
            hidden:false
        }
    })
</script>

<!--这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效。
 这是语句,不是表达式
{{ var a = 1 }}

 流控制也不会生效,请使用三元表达式
{{ if (ok) { return message } }}

模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如 Math 和 Date 。你不应该在模板表达式中试图访问用户定义的全局变量。

-->

计算属性

计算属性

<div id="example">
    品牌名称: <input type="text" v-model="brandName"></input>
    <p>首字母:{{firstLetter}}</p>
</div>
</body>

<!--计算属性 对于任何复杂逻辑,你都应当使用计算属性。
 Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。
当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。
然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。细想一下这个例子:-->
<script>
    var vm = new Vue({
        el: "#example",
        data: {
            brandName:"Adidas",
        },
        // 计算属性
        computed:{
            firstLetter:{
                // 计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:
                get:function () {
                    var brandName = this.brandName;
                    // 取首字母,并转大写
                    var firstLetter = brandName.substr(0,1).toUpperCase();
                    return firstLetter;
                },
                // 另外set设置属性,并不是直接修改计算属性,而是修改它的依赖。
                set: function (newValue) {
                  //this.firstLetter = newValue 这种写法会报错
                   this.brandName = newValue;
                }
            }
        }
    })
</script>

计算属性缓存 vs 方法

我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。

watch 侦听器

侦听属性

<div id="example">
    品牌名称: <input type="text" v-model="brandName"></input>
    <p>首字母:{{firstLetter}}</p>
</div>
</body>

<script>
    var vm = new Vue({
        el: "#example",
        data: {
            brandName: "Adidas",
            firstLetter:''
        },
        // 计算属性
        watch: {
            brandName: function (newVal,oldVal) {
                this.firstLetter = newVal.substr(0,1).toUpperCase();
            }
        }
    })
</script>

watch 与 computed 对比

image-20210416095756894

从上面流程图中,我们可以看出它们之间的区别:

  • watch:监测的是属性值, 只要属性值发生变化,其都会触发执行回调函数来执行一系列操作。
  • computed:监测的是依赖值,依赖值不变的情况下其会直接读取缓存进行复用,变化的情况下才会重新计算。

除此之外,有点很重要的区别是:计算属性不能执行异步任务,计算属性必须同步执行。也就是说计算属性不能向服务器请求或者执行异步任务。如果遇到异步任务,就交给侦听属性。watch也可以检测computed属性。

v-bind 缩写

<!-- 完整语法 -->
<a v-bind:href="url">...</a>

<!-- 缩写 -->
<a :href="url">...</a>

<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>

v-on 缩写

<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>

<!-- 缩写 -->
<a @click="doSomething">...</a>

<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>

Vue生命周期

生命期钩子

<body>
    <div id="app">
    </div>
</body>

<!--每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,
需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。
同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如 created 钩子可以用来在一个实例被创建之后执行代码:-->
<!--也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted、updated 和 destroyed。
生命周期钩子的 this 上下文指向调用它的 Vue 实例。-->
<script>
    new Vue({
        data: {
            a: "初始化"
        },
        created: function () {
            // `this` 指向 vm 实例
            alert('a is: ' + this.a)
            // => "a is: 1"
        }
    })
</script>

下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。

Vue 实例生命周期

生命周期钩子:cn.vuejs.org/v2/api/#cre…

组件化

组件基础

<body>
    <!--因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,
    例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。-->
    <div id="components-demo">
        <button-counter></button-counter>
        <!-- 解析结果
        <div id="components-demo"><button>点了我 8 次.</button></div>
        -->

        <!-- 组件的复用 -->
        <button-counter></button-counter>
        <button-counter></button-counter>
        <!--注意当点击按钮时,每个组件都会各自独立维护它的 count。因为你每用一次组件,就会有一个它的新实例被创建。-->
    </div>
</body>

<script>
    // 定义一个名为 button-counter 的新组件
    Vue.component('button-counter', {
        // 一个组件的 data 选项必须是一个函数
        // 当我们定义这个 <button-counter> 组件时,你可能会发现它的 data 并不是像这样直接提供一个对象:data:{count:0}
        // 如果 Vue 没有这条规则,点击一个按钮就可能会像如下代码一样影响到其它所有实例
        data: function () {
            return {
                count: 0
            }
        },
        template: '<button v-on:click="count++">点了我 {{ count }} 次.</button>'
    });

    /*为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。
    至此,我们的组件都只是通过 Vue.component 全局注册的:
    Vue.component('my-component-name', {
        // ... options ...
    })
    全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。
    */

    new Vue({
        el: '#components-demo'
    });

</script>

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:

Component Tree

参考

用jquery实现的简单数据双向绑定

vue官方文档

详解Vue计算属性和侦听属性