美文网首页
2019-05-30Vue系列一之前端基本情况及VUE指令

2019-05-30Vue系列一之前端基本情况及VUE指令

作者: 啊_6424 | 来源:发表于2019-05-30 18:24 被阅读0次

    验证码机制

    在后端里,总是认为前端有可能会被伪造。页面上的验证码是后端随机产生的(也可以前端生成,但不建议)

    步骤:
    • 1.后端调用相关的绘图第三方类库,或是(平台PHP,.NET,Java)系统核心绘图类库进行图片的绘制
    • 2.绘制的那些随机的数字、字母都是后端预先定义好的
    • 3.绘制图片的URl地址通过网络发送给客户端,然后,客服端可以通过img标签去引用这个验证码的地址
    • 4.后端在绘制完毕验证码后,随机选择生成的字母不能丢弃而是需要保存到session中,可用于识别哪个用户
    • 5.当客服端输入验证码完毕后会提交表单,后端会拿到相关数据与session中的验证码进行比较,一样则通过

    前端发展史:

    原生JS----jQuery之类的类库----模板引擎----MVVM框架

    • 原生JS:API难懂,还得兼容各种浏览器
    • jQuery:解决了浏览器兼容问题,但还是得频繁的操作DOM元素,不断的拼接字符串,心力交瘁
    • 模板引擎:只需要调用模板引擎提供的一些方法就可以把DOM元素生成,不需要开发者自己渲染页面
    • MVVM框架:
      MVVM一直与MVC一起出现在文章中,要注意区别他俩:
      • MVC是后端开发分层开发概念
      • MVVM是前端视图层的概念,主要关注于视图层分离
    传统的MVC,站在整个项目,综合考虑前端,后端

    Model: 数据的拥有者,实现具体的业务逻辑,是业务逻辑模型而不是数据模型。
    View: 具体的用户界面,如按钮、列表、图片。
    Controller: 负责将 View 中用户的动作传达给 Model,将 Model 的数据通过 View 展现出来。


    MVVM

    模型(Model):数据模型
    视图(View):调用ViewModel的方法并响应变化。
    视图模型(ViewModel):业务逻辑。

    前端三大主流框架:

    • Vue.js
      很火,能开发手机APP,需要借助weex
      适合做单页面应用程序
    • React.js
      很流行,也能开发手机APP
      适合做单页面应用程序
    • Angular.js
      适合做单页面应用程序

    框架和库的区别:

    框架

    提供一套完整的解决方案,对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目

    提供小功能,类似一个插件,对项目侵入性小,如果某个库无法完成需求,可以很容易切换到其他库实现需求。
    例如从jQuery切换到zepto,从EJS切换到art-template

    Vue.js 是什么

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

    Vue.js的代码与MVVM之间的对应关系

    一个简单的例子

    Vue的基本代码结构和插值表达式

      <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    ......
      <div id="app">
        <p>{{msg}}</p>
      </div>
    ......
    <script>
      var vm = new Vue({
        el:"#app",
        data:{
          msg:"123"
        }
      })
    </script>
    

    当用script引入vue时,window中多了一个vue的构造函数,通过new,创建一个vue对象vm。
    el:表示这个vue实例控制的页面区域,不能绑定到body上面去
    data:存放el中要用到的数据,通过指令或者插值表达式渲染到页面。
    指令:在后面的模块学习
    插值表达式{{}}:花括号里边写数据的名字

    vue的指令

    • v-cloak:解决页面加载闪烁

    当网络很差,或者其他一些原因导致页面加载闪烁,出现指令或者标签,非常影响用户观感,可以用这个指令解决。
    通常是下面这样两种情况时会发生闪烁:

    <p>{{msg}}</p>//插件表达式时闪烁
    <p v-html="msg"></p>
    

    解决办法:给挂载元素添加v-cloak指令,再在style里边定义一个样式就可以了

    <style>
      [v-cloak] {
        display: none;
      }
    </style>
    .......
     <div id="app" v-cloak>
        <p>{{msg}}</p>
      </div>
    ......
    <script>
      var vm = new Vue({
        el:"#app",
        data:{
          msg:"123"
        }
      })
    </script>
    
    • v-text

    写法:

    <p v-text="msg"></p>
    

    作用:将msg显示在页面上。

    v-text指令与插件表达式的区别与相同点
      1. v-text没有加载闪烁问题
      1. v-text会覆盖元素原本的内容,但插值表达式只会替换占位符
      1. v-text 与差值表达式都会把msg当成普通文本来处理
     <p>{{msg2}}</p>
     <p v-text="msg2"></p>
    ......
     msg2:"<h1>我是h1标签</h1>"
    
    都把标签当成普通文本处理

    那么,如何渲染msg2呢?

    • v-html

    渲染带有标签的文本,会覆盖原本的内容

    //添加这句
        <p v-html="msg2">hhhh
          <span>jjjj</span>
        </p>
    
    用v-html渲染出来了

    v-bind 绑定属性

    写法:

    <div :class="div"></div>
    <div v-bind:class="div"></div>
    
    <div id="app">
      <input type="text" value="按钮" title="myTitle">
    </div>
    <script>
      var vm = new Vue({
        el:"#app",
        data:{
          myTitle:"这里是input标签的title"
        }
      })
    </script>
    
    给title属性绑定值,但这样明显不对

    那该怎么办呢?用v-bind标签

    <div id="app">
      <input type="text" value="按钮"  v-bind:title="myTitle">
    </div>
    <script>
      var vm = new Vue({
        el:"#app",
        data:{
          myTitle:"这里是input标签的title"
        }
      })
    </script>
    
    这才是我们想要的结果

    v-bind指令在解析变量时,当成了js表达式去解析,故而可以有如下写法:

    <input type="text" value="按钮" v-bind:title="myTitle + '123'">
    
    image.png

    v-on 添加事件

    写法:

    ......
     <input type="text" value="按钮"  v-on:click="alert('aaaa')">
    //或者
    <div @click="test">点击</div>
    ......
    <script>
      var vm = new Vue({
        el:"#app",
        methods:{
          test:function(){
            alert("点击");
          }
        }
      })
    </script>
    
    事件修饰符
    • .stop:相当于JavaScript中的event.stopPropagation(),防止事件冒泡
    ......
       <div class="outer" @click="outer">
          <div class="middle" @click="middle">
            <button class="inner" @click="inner">点击</button>
          </div>
        </div>
        <p v-text="text"></p>
    ......
    <script>
      var vm = new Vue({
        el:"#app",
        data:{
          text:"测试事件冒泡"
        },
        methods:{
          outer:function(){
            this.text="outer";
            console.log("outer");
          },
          middle:function(){
            this.text="middle";
            console.log("middle");
          },
          inner:function(){
            this.text = "inner";
            console.log("inner");
          }
        }
      })
    </script>
    
    点击后,页面最终显示outer
    可以看到事件的执行顺序是这样的

    这种情况就是事件冒泡,原生JS通过event.stopPropagation()阻止,在vue中,可以通过.stop来阻止。

        <div class="outer" @click="outer">
          <div class="middle" @click="middle">
            <button class="inner" @click.stop="inner">点击</button>
          </div>
        </div>
    
    可以看到只执行了inner函数
    • .prevent:相当于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播)
      比如a链接有默认的跳转行为,下面的demo点击后会执行函数并跳转页面,可若我们不想跳转页面的话,该怎么办呢?
        <div class="container">
          <a href="http://baidu.com" @click="linkClick">跳转到百度</a>
        </div>
    ......
          linkClick:function(){
            console.log("触发了链接的点击事件");
          }
    

    改为下面这样就好了

     <a href="http://baidu.com" @click.prevent="linkClick">跳转到百度</a>
    
    触发了事件也取消了跳转页面
    • .capture:添加事件侦听器时使用事件捕获,与事件冒泡的方向相反,事件捕获由外到内


      图片来自其他博客,详见参考

      略微修改阻止冒泡的demo代码

        <div class="outer" @click.capture="outer">
          <div class="middle" @click="middle">
            <button class="inner" @click="inner">点击</button>
          </div>
        </div>
        <p v-text="text"></p>
    
    先outer,再inner最后middle

    这是因为先因为捕获机制执行了outer,再默认冒泡机制执行inner和middle,如果想从外到内依次执行的话,给middle也加上捕获机制

    <div class="outer" @click.capture="outer">
          <div class="middle" @click.capture="middle">
            <button class="inner" @click="inner">点击</button>
          </div>
        </div>
        <p v-text="text"></p>
    
    从外到内一次执行
    • .self:只会触发当事件在该元素本身的事件(不包含子元素)
        <div class="outer" @click="outer">
          <div class="middle" @click.self="middle">
            <button class="inner" @click="inner">点击</button>
          </div>
        </div>
        <p v-text="text"></p>
    

    点击按钮并没有执行outer,但是执行了outer,这是.self跟.stop的区别

    • .once:事件只会触发一次
        <div class="container">
          <a href="http://baidu.com" @click.prevent.once="linkClick">跳转到百度</a>
        </div>
    

    点击第一次,阻止了默认行为,触发了点击函数,点击第二次的时候,没有触发点击函数,默认行为也执行了(即跳转到了百度页面),调换事件修饰符位置效果也一样
    注意事件修饰符可以连用

    区别事件修饰符的应用场合

    .self:只阻止自己的冒泡,外层还能继续冒泡
    .stop:阻止了自己及往外层的的冒泡行为

    v-model:表单元素的数据双向绑定

    只能用于表单元素中
    比如有一input,我们想要获取输入的值,按照学习,应该是用v-bind绑定我们的value属性

        <div class="container">
          <input type="text" v-bind:value="msg">
        </div>
    ......
     msg:"双向数据绑定",
    
    先将数据从M渲染到了V
    但并没有将用户在V修改的数据绑到M

    原因就是v-bind只能单向绑定。修改为:

        <div class="container">
          <input type="text" v-model="msg">
        </div>
    
    v-model也能正确的渲染
    可以看到,用户的输入绑定到了M

    在vue中使用样式

    一、使用class样式

    原生形式:

    <style>
      .red{
        color:red;
      }
      .italic{
        font-style: italic;  
      }
      .thin{
        font-weight: 10;
      }
      .active{
        letter-spacing:0.5em;
      }
    </style>
    <body>
      <div class="" id="app">
        <h1 class="red italic thin">这是一个h1标签</h1>
      </div>
    </body>
    </html>
    <script>
      var vm = new Vue({
        el:"#app",
        data: {
    
        },
        methods: {
    
        }
      });
    </script>
    
    1.数组

    直接传递一个数组,这里的class需要使用v-bind绑定,类名需要写引号,不写的话会去data里面找数据

        <h1 :class="['red','italic','thin']">这是一个h1标签</h1>
    
    2.数组中使用三元表达

    会先去data里面找flag变量,为true则返回'active'

           <h1 :class="['red','italic','thin',flag?'active':'']">这是一个h1标签</h1>
    ......
          flag:true
    
    3.数组中嵌套对象

    因为三元表达式麻烦,不好写,也不好理解,所有可以用这种形式
    flag为true时有active,false时没有active

        <h1 :class="['red','italic','thin',{'active':flag}]">这是一个h1标签</h1>
    //或
        <h1 :class="['red','italic','thin',{active:flag}]">这是一个h1标签</h1>
    

    进一步可以定义到data里边

          <h1 :class="classList">看一看,瞧一瞧哪!!!!</h1>
    .......
          flag:true,
          classList:['red','italic','thin',this.flag?'active':'']
    
    4.直接使用对象

    对象里属性就是类名,属性值是一个标识符。由于对象的属性可带引号,可以不带引号,故这里类名加不加引号无所谓

        <h1 :class="{red:true,italic:true}">这是一个h1标签</h1>
    //或
        <h1 :class="{'red':true,'italic':true}">这是一个h1标签</h1>
    //或
        <h1 :class="{red:true,'italic':true}">这是一个h1标签</h1>
    
    

    咱们可以进一步把对象定义到data里边,再通过属性引用

        <h1 :class="classObj">这是一个h1标签</h1>
    .......
        classObj : {red:true,italic:true}
    
    二、使用内联样式
    1.直接在元素上通过:style的形式,书写样式对象
    2.将样式对象定义到data对象中,直接引用到:style
    3.在:style中通过数组,引用多个data上的样式对象

    v-for:循环

    1.迭代数组

    按照以前学的,咱可以这样迭代数组

        <p>{{list[0]}}</p>
        <p>{{list[1]}}</p>
        <p>{{list[2]}}</p>
        <p>{{list[3]}}</p>
        <p>{{list[4]}}</p>
    ......
        list:[1,2,3,4,5]
    

    但是这样太low了,我们可以使用v-for指令

       <p v-for="item in list">{{item}}</p>
    //或
       <p v-for="(item,index) in list">索引值:{{index}},每一项的内容:{{item}}</p>
    
    迭代纯数组
       <p v-for="item in user">id是:{{item.id}},name为:{{item.name}}</p>
       <p v-for="(item,index) in user">索引值:{{index}},id是:{{item.id}},name为:{{item.name}}</p>
    ......
          user:[
            {id:1,name:"zs"},
            {id:2,name:"sd"},
          ]
    
    迭代对象数组
    2.迭代对象中的属性
    <p v-for="(val,key) in people">值:{{val}},键:{{key}}</p>
    //或
    <p v-for="(val,key,index) in people">值:{{val}},键:{{key}},索引值值:{{index}}</p>
    ......
          people:{
            id:1,
            gender:"女",
            name:"Jan"
          }
    
    渲染出了键值对=和索引值
    3.迭代数字
       <p v-for="count in 10">这是第{{count}}次循环</p>
    
    注意count从1开始计数

    总结:in 后面可以放 普通数组,对象数组,对象,数字

    v-for中的key

    在2.2.0+的版本中,当在组件中使用v-for时,或者一些特殊情况下,key是必须要写的。

    当vue.js用v-for正在更新已渲染的元素列表时,他默认是使用就地复用策略,如果数据项的顺序被改变,Vue将不是移动DOM元素来匹配数据项的顺序,而是简单复用此时每个元素,并且确保他在特定索引下显示已被渲染的每个元素。

    为了给Vue一个提示,以便它能跟踪每个节点的身份,从而复用和重新排序现有元素,需要为每项提供一个唯一key属性。
    在尾部添加

        <div>
          <label>ID:<input type="text" v-model="id"></label>
          <label>姓名: <input type="text" v-model="name"></label>
          <input type="button" value="添加" @click="addGaint">
        </div>
        <p v-for="(item,index) in gaint">
         <input type="checkbox">{{item.id}}   {{item.name}}
        </p>
    ......
    data:{
     gaint:[
            {id:1,name:"李斯"},
            {id:2,name:"嬴政"},
            {id:3,name:"赵高"},
            {id:4,name:"韩非"},
            {id:5,name:"荀子"}
          ],
          id:0,
          name:""
    },
    
    methods:{
       addGaint:function(){
            this.gaint.push({id:this.id,name:this.name});
          }
    }
    
    
    无论选没选中,在尾部添加都没有bug

    在头部添加

     addGaint:function(){
            this.gaint.unshift({id:this.id,name:this.name});
      }
    
    直接添加时,吕不韦被正常渲染在了第一个,我们选中荀子后再点击添加,结果如下图
    吕不韦正常渲染出来了,但是选中状态从荀子变为了韩非

    这就是因为没有标识,记住的是选中了第6个而不是选中的荀子。
    解决方案就是加上key(key只能是Number或者String,而且用v-bind绑定),它能强制地让我们data里的属性跟页面上地显示关联起来

        <p v-for="(item,index) in gaint" :key="item.id">
         <input type="checkbox">{{item.id}}   {{item.name}}
        </p>
    
    再选中荀子添加,添加完后选中的还是荀子

    v-if ,v-show

    总结:一般来说,v-if有更高的切换消耗(因为每次切换都涉及到DOM元素的删除和创建),而v-show有更高的初始渲染消耗(比如一直为false,不太可能变为true的标签,用这个的话也要进行渲染)。
    因此,如果需要频繁切换v-show较好,如果在运行时条件不大可能改变v-if较好。

        <button @click="flag = !flag">切换</button>
    //这里不能简写为!flag,因为这样的话就不会重新赋值
        <p v-if="flag">这是v-if控制的标签</p>
        <p v-show="flag">这是v-show控制的标签</p>
    ......
    data:{
      flag:true,
    }
    
    flag为false时,v-if控制的标签被移除了

    课程内容总结:

    看看自己能回顾多少

    参考资料:

    前端历史
    事件修饰符

    相关文章

      网友评论

          本文标题:2019-05-30Vue系列一之前端基本情况及VUE指令

          本文链接:https://www.haomeiwen.com/subject/ajmvtctx.html