vue是采用自底向上增量开发设计的一套构建用户界面的渐进式框架,它不仅易上手且方便。

  vue的安装有三种方式,官网直接进行下载;使用在线的CND(https://unpkg.com/vue@2.6.11/dist/vue.js);使用npm install vue 命令进行下载。获取后直接在script标签中引入就可。

  对于vue最简单的应用将其当成是一个模板引擎,采用模板语法把数据渲染进DOM.如下:

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

  每个vue.js应用都是通过构造函数Vue创建一个Vue的根实例来进行的,常使用vm(vue model)这个变量名表示实例。在实例vue时,要传入一个选项对象,它可以包含数据,模板,元素,方法,生命周期等等。下面为Vue()构造函数传入了一个对象,对象中包含了el和data这两个参数。el参数,用于提供一个在页面上已存在的DOM元素作为Vue实例挂载目标。而data则表示Vue实例的数据对象。

let vm = new Vue({
  //选项 el:
"#app", data:{ message:'davina' } })

  一、vue模板的内容

  对于{{}}它主要的作用是进行数据绑定,最常见的是使用Mustache语法({{}}语法)的文本插值。上文中的message相当于一个变量或者是占位符,最终它会表示为真正的文本内容。Mustache标签将会被数据对象上(data中的message)的值进行替代。当massage上的内容发生改变时,插值处的内容也会进行更新。

  表达式插值。下面的这些表达式会在所属的vue实例的数据作用域下作为js被解析。每个绑定只能包含单个表达式,需要注意的是不能是语句,它包括定义变量,定义函数,赋值等待。

    {{number +1}}
    {{value?'yes':'no'}}
    {{ 对象 }}
    {{ 数组 }}
    {{函数的返回值}}

示例:

    <div id="app">
        {{msg}}<br>
        {{[1,2,3].map((item)=>{return item*2})}}<br>
        {{arr}}<br>
        {{obj}}
    </div>
<!-- 导入vue.js -->
<script src="./vue.js"></script>
<script>
    // vm是vue的实例
    let vm = new Vue({
        el: '#app',//指定vue替换元素
        data: {
            msg: 'test',
            obj: { age: 20 },
            arr: [1, 2, { name: "ph" }],
        }
    });
</script>

  二、指令

  在模板的元素中,那个v-xxx行内属性就是Vue的指令,它有常用即有指令和自定义指令。

  1、即有指令(13)

  v-model="xxx": 一般用于表单元素上,创建双向数据绑定。input框内容改变 ,所有用到这个变量的地方都会自动进行更新。像下面的例子中,在input框中输入其它的内容,上面msg的内容也会被修改。

    <div id="app">
        <!-- textarea -->
        <textarea v-model='text'></textarea><br>
        <!-- select -->
        <h2>{{selectValue}}</h2>
        <!-- 多个选择都是数组 -->
        <select v-model='selectValue' multiple>
            <option value="" disabled>请选择</option>
            <option v-for='i of selectOptions' :value="i.id">{{i.value}}</option>
        </select><br>
        <!-- radio 分组互斥-->
        <input type="radio" value="" v-model="radioValue">
        <input type="radio" value="" v-model="radioValue"><br>
        <!-- checkbox 默认值是不选择 true false -->
        爱好:{{checkValue}}
        <input type="checkbox" value="吃饭" v-model="checkValue">
        <input type="checkbox" value="睡觉" v-model="checkValue">
        <input type="checkbox" value="打豆豆" v-model="checkValue"><br>
        <!-- 修饰符 -->
        <!-- trim是前去除前后的空格,但中间的不能去,number限制只能输入数字 -->
        <input type="text" v-model.trim="text">
        <input type="text" v-model.number="text">
    </div>
    <script src="./vue.min.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                text: 'davina',
                selectValue: [],
                selectOptions: [
                    { value: 'js', id: 1 },
                    { value: 'react', id: 2 },
                    { value: 'vue', id: 3 }
                ],
                radioValue: '',
                checkValue: ['吃饭', '睡觉', '打豆豆'],
            }
        })
    </script> 

  v-text="xxx": 这个不太常用。主要用于更新textContent,可以等价于js中的text属性

  v-html=“xxx”: 双大括号的方式会将数据解析为纯文本,而不是html。如果是真正的要输出html标签要用到这个v-html指令,它等价于js中的innerHTML。

   <div id="app">     
    <h4 v-text="str"></h4>
    <!-- <h4>{{str}}</h4> -->
    <h4 v-html="str"></h4>
    </div>
<script>
    let vm = new Vue({
        el:'#app',
        data:{
            str:'<i>test</i>'
        }
    });
</script> 

  v-if="xxx": Vue会根据表达式的值真假条件来渲染元素,它可以实现条件渲染,用来控制元素或者组件是否进行加载,它有比较大的切换开销;

  v-else: 搭配v-if来进行使用的,它必须紧跟在v-if/v-else-if后面,不然是不起作用的;

  v-else-if: 它充当v-if中的else-if块,可以链式使用多次

   <div id="app">     
    <h2 >{{msg}}</h2>
    <input type="text" v-if="msg.length < 10 " v-model="msg">
    <h2 v-else>内容太长,不再显示</h2>
    </div>
<script>
    let vm = new Vue({
        el:'#app',
        data:{
            msg:'msg'
        }
    });
</script>       

  v-show="xxx": 用来控制元素或者组件是否显示,和v-if不同的是如果v-if的值是false那么这个元素将销毁,不在DOM中,但v-show的元素会始终被渲染保存在DOM中,它只是简单的切换了css中的display属性,有比较大的初始化加载开销。

  v-for="xxx": 用来循环展示标签的,可以循环数组,数字,字符串,对象(基本上都是数组);需要注意的是v-for和v-if同时使用时,for的优先级高(不建议一起使用),还用一般要带一个:key,对于vue来说是元素的一个身份证明,有利于Vue中的DOM DIFF计算。j理想的key是数据的唯一ID,如果没我们可以用索引,但这时有可能会导致元素不更新复用了老的元素。有以下两种形式。

<div v-for="item of items"></div> //使用of 
<div v-for="(item,index) in items"></div> //使用in index表示当前项的索引  item 数组中的每一项
    <div id="app">
        <h3 v-for="(index,item) in ary" :key="index">{{item}}:{{index}}</h3>
    </div>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            ary: [1, 2, 3, 4]

        }
    });
</script>

  v-bind="xxx": 用来动态绑定一个或者多个特性,处理行内属性。没有参数时,可以绑定到一个包含键值对的对象。可以简写用冒号(:)来表示。常用于绑定style,class所以Vue对其进行了专门的强化:class="{类名1:值,类名2:值,......}",:style="{属性名:属性值,......}"。

    <style>
        .box {
            color: lightblue
        }
    </style>
    <div id="app">
        <a :href="url" :class="cln">click me</a>
    </div>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            url: 'https://www.baidu.com/img/flexible/logo/pc/result@2.png',
            cln: 'box'
        }
    });
</script>

  v-cloak: 保持在元素上直到关联实例结束时进行编译。Vue专门用来提供解决小胡子显示问题的,它需要配合css来使用,当vue编译完成后,会把这个属性删掉,这时css属性就不起作用了。

  <style>
       [v-cloak]{
           opacity: 0;
       }
   </style>
   <div id="app" v-cloak>     
        <h5>{{msg}}</h5>
    </div>
<script>
    let vm = new Vue({
        el:'#app',
        data:{
            msg:'message'
        }
    });
</script> 

  v-once: v-once关联的实例,只能编译一次。实例及所有的了节点将被视为静态内容进行跳过,可以用于优化更新性能。

   <div id="app" v-once>     
    <h5>{{msg}}</h5>
    <p>{{ary}}</p>
    </div>
<script>
    let vm = new Vue({
        el:'#app',
        data:{
            msg:'message',
            ary:[1,2,3]
        }
    });
</script> 

  v-pre: 有这个指令的标签及其后代元素,vue都不在编译,主要用来跳过这个元素和它的子元素编译过程,用来提升编译效率的。 

   <div id="app">     
    <ul v-pre>
        <!-- 里面的内容不用vue来操作,可以提升效率 -->
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    </div>
<script>
    let vm = new Vue({
        el:'#app'
    });
</script>    

   v-on: 专门用来绑定事件的指令,可以简写成@。

<div id="app">
        <h2>{{count}}</h2>
        <button @click="add"> + </button>
        <button @click="minus"> - </button><br>
         <!-- 在函数名后面加上()不是为了执行,而是为了传参 -->
        <button @click="add(10,$event)"> +10 </button>
        <button @click="minus(-10)"> -10 </button><br>
        <!-- 
        @click='fn'                         这种情况默认把事件对象传过去
        @click="fn()"                       一个参数都没有那就是把函数执行
        @click="fn(10,20,...)"              这种情况 写什么参数就传递什么参数
        @click="fn(10,$event,20,$event)"    这种情况是即需要事件对象(编写$event),也需要自己传递的参数 
        -->
</div>
<script src="./vue.js"></script>
<script>
    let vm = new Vue({
        el: '#app',
        data: { count: 0 },
        methods: {
            //这里放的是各种函数,函数当前实例都是this
            //这里的属性会被挂载到实例上,所以与data中的属性名不能重复
            add(n) {
                typeof n == "object" ? this.count++ : this.count += n;
            },
            minus(n) {
                typeof n == 'object' ? this.count-- : this.count -= n;
            }
        }
    });
</script>

  还有事件修饰符:.stop:阻止事件继续传播 / .prevent:事件不再重载页面 / .capture: 使用事件捕获模式 / .self:只当在event.target是当前元素时触发 / .once:事件将只会触发一次 / .passive:告诉浏览器不想阻止事件的默认行为

  需要强调一点的是,使用修饰符顺序很关键,相应的代码会以同样的顺序产生。在大部分事件中,先执行绑定的函数,再执行默认的函数,默认的函数也有执行的顺序。但在onscroll,touchmove这类高频触发的事件是先执行默认函数函数,再执行绑定函数。

<body>
    <div id="app">
        <h2>{{count}}</h2>
        <div class="outer" @click.once='add'>
            outer
            <div class="inner" @click.stop="stop">
                inner
                <div class="center">
                    center
                </div>
            </div>
        </div>
         <!-- 当然还有按钮修饰符 -->
         <input type="text"  @keydown.enter="enter">
    </div>
</body>
</html>
<script src="./vue.js"></script>
<script>
    let vm = new Vue({
        el: '#app',
        data: { count: 0 },
        methods: {
            add(n) {
                typeof n == "object" ? this.count++ : this.count += n;
            },
            minus(n) {
                typeof n == 'object' ? this.count-- : this.count -= n;
            },
            prevent(e) {
                // e.preventDefault();
            },
            stop(e) { e.stopPropagation() },
            enter(e) { console.log(e) }
        }
    });
</script>

  2、自定义指令

  Vue除了提供默认的内置指令以外,还可以让开发者根据实际情况来自定义指令。通过它我们可以DOM元素进行更多的底层操作。它存在着全局注册和局部注册两种方式。

  通过Vue.directive(id,[definintion])方式来进行注册,第一个参数为自定义指令的名称,第二个参数可以是对象数据也可以是一个函数。需要注意的一点是指令名称不需要加v-,默认是自动加上的,但在使用时要加上v-前缀。

<body>
    <div id="app">
        <h3 v-col='"lightblue"'>{{msg}}</h3>
        <h5 v-col>{{msg}}</h5>
    </div>
</body>
<script>
    Vue.directive('col', function (el, obj) {
        //对函数中的this为window 不在是当前的实例了
        console.log(this);
        //el 使用这个指令的那个元素标签 
        //obj中有一个value值,它对应的是指令后面跟的值。如果没有则不存在
        console.log(el, obj);
        el.style.color = obj.value || 'lightpink';
    })
    let vm = new Vue({
        el: '#app',
        data: {
            msg: "自定义指令之全局注册"
        }
    });
</script>

  局部注册我们可以通过在Vue实例中添加directives对象数据来进行注册。在工作中如果有多个自己定义的指令,一般会单独新建一个文件,用import或者script进行引入。先执行局部再用全局指令。

<body>
    <div id="app">     
        <h5 v-col>{{msg}}</h5>
    </div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            msg: "自定义指令之全局注册"
        },
        directives: {
            col(el, obj) {
                el.style.color = 'lightskyblue'
            }
        }
    });
</script>

  一个指令定义对象可以提供如下几个钩子函数,一般用的比较多的时insert,bind和unbind。

    bind: 只调用一次,指令第一次绑定到元素时进行调用;

    unbind: 只调用一次,指令与元素解绑时调用;

    insert: 被绑定元素插入父节点时调用;

    update: 所在组件的VNode更新时调用,但也可能是发生在其子元素的VNode更新之前;

    componentUpdated: 所在组件的VNode及其子元素的VNode全部更新时调用

    它们中的每一个都以el,binding,VNode参数:

    el: 指令所绑定的DOM元素,可以直接用来操作DOM

    binding: 一个对象。包含了以下属性name,value,oldValue,expression,arg,modifiers.

    VNode:Vue编译生成的虚拟节点

    oldVnode: 上一个虚拟节点,用来区分传递的旧值和新值,仅在update和componentUpdated钩子中可用。

  下面这个例子可用于多个权限的设置,需要注意的是inserted函数的使用。

<body>
    <div id="app">
        <h3 v-premission='"张三"'>{{msg}}</h3>
    </div>
</body>
<script>
    let ary = ["张三", "赵二", "王五", "李六"];
    Vue.directive('premission', {
        //inserted是钩子函数它是固定的
        inserted(el, { value }) {
            //这个函数执行的时候 代表 编译好的元素已经插入到了父结点中
            let bol = ary.indexOf(value) == -1 ? false : true;
            if (!bol) {
                el.parentNode.removeChild(el);
            }
        }
    })
    let vm = new Vue({
        el: '#app',
        data: {
            msg: "权限"
        }
    });
   <div id="box">
        <input type="text" v-focus.color='color'>
    </div>
    <script>
        // 需求:让输入框自动获取焦点
        //全局指令:所以组件,实例都可以使用
        Vue.directive('focus', {
            //指令元素插入到页面时执行
            inserted(el, obj, vnode) {
                el.focus();
                //el 当前指令元素 obj 绑定属性 vnode虚拟节点 contex上下文,当前指令所在的上下文
                // console.log(el, obj, vnode);
                obj.modifiers.color ? el.style.background = obj.value : lightblue;
            },
            //绑定时执行
            // bind(el, obj, vnode) {
            //     Vue.nextTick(() => {
            //         el.focus();
            //     })
            // }
            //指令销毁时会触发这个函数
            // unbind(){}
        })
        let vm = new Vue({
            el: '#box',
            data: {
                color: 'lightgreen',
            }
        })
    </script>
    <style>.content {height:30px;width: 120px;background-color: lightblue}</style>
    <div id="app">
//弹层功能 <div v-click-outside> <button>click </button> <input type="text"> <div class="content" v-if="isShow">xxxx年xx月xx日 </div> </div> </div> <script> //判断是否存在当前的dom中 let vm = new Vue({ el: '#app', directives: { clickOutside: { bind(el, bindings, vnode) { el.fn = (e) => { if (el.contains(e.target)) { vnode.context['focus']() } else { vnode.context['blur']() } } document.addEventListener('click', el.fn) }, unbind(el) { document.removeEventListener('click', el.fn) } } }, data: { isShow: false }, methods: { blur() { this.isShow = false; }, focus() { this.isShow = true; } } }); </script>

 

   

  

    

 

 

 

 

posted on 2020-07-18 15:19  人称小小贩  阅读(298)  评论(1编辑  收藏  举报