《web前端全栈成长计划》Vue第一章学习笔记(下)

举报
张辉 发表于 2020/09/07 16:57:44 2020/09/07
【摘要】 web前端全站成长计划第三阶段vue课程第一章的学习笔记(下)

10 vue List搜索和排序

10.1 代码和笔记

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>06_列表渲染_过滤与排序</title>
</head>
<body>
<!--
1. 列表过滤
2. 列表排序
-->

<div id="demo">
  <input type="text" v-model="searchName">
  <ul>
    <!-- filterpersons是persons数组过滤后的结果,是根据person和searchName计算出来的,
    所以需要使用计算属性 computed
    -->
    <li v-for="(p, index) in filterPersons" :key="index">
      {{index}}--{{p.name}}--{{p.age}}
    </li>
  </ul>
  <div>
    <button @click="setOrderType(2)">年龄升序</button>
    <button @click="setOrderType(1)">年龄降序</button>
    <button @click="setOrderType(0)">原本顺序</button>
  </div>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  new Vue({
    el: '#demo',
    data: {
      searchName: '', //搜素栏的值
      orderType: 0, // 0代表不排序, 1代表降序, 2代表升序
      persons: [
        {name: 'Tom', age:18},
        {name: 'Jack', age:17},
        {name: 'Bob', age:19},
        {name: 'Mary', age:16}
      ]
    },

    computed: {
      filterPersons () {
//        debugger
        // 取出相关数据,一旦以下三个内容发生变化,就会执行
        const {searchName, persons, orderType} = this
        //最终需要显示的数组
        let arr = [...persons]
        // 过滤数组
        if(searchName.trim()) {
          arr = persons.filter(p => p.name.indexOf(searchName)!==-1)
        }
        // 排序
        if(orderType) {
          //sort需要传递比较函数

          arr.sort(function (p1, p2) { //如果返回负数代表P1在前,返回正数代表P2在前
            if(orderType===1) { // 降序
              return p2.age-p1.age
            } else { // 升序
              return p1.age-p2.age
            }

          })
        }
        return arr
      }
    },

    methods: {
      //定义设置顺序的方式,比jquery简单的多
      setOrderType (orderType) {
        this.orderType = orderType
      }
    }
  })
</script>
</body>
</html>

10.2 执行效果

10.2.1 原始页面

image.png

10.2.2 搜索a

image.png

10.2.3 升序

image.png

10.2.4 降序

image.png

10.2.5 原本顺序

image.png


11 vue 事件处理

11.1 代码和笔记

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>07_事件处理</title>
</head>
<body>
<!--
1. 绑定监听:
  v-on:xxx="fun"
  @xxx="fun"
  @xxx="fun(参数)"
  默认事件形参: event
  隐含属性对象: $event
2. 事件修饰符:
  .prevent : 阻止事件的默认行为 event.preventDefault()
  .stop : 停止事件冒泡 event.stopPropagation()
3. 按键修饰符
  .keycode : 操作的是某个keycode值的健
  .enter : 操作的是enter键
-->

<div id="example">

  <h2>1. 绑定监听  <!--  如果不传参数,默认传了event
   -->
   <button @click="test1">test1</button>
   <button @click="test2('abc')">test2</button>
   <!--  得到button的文本
   event 代表事件对象
   既要传值,又要传event ...
   -->
  <button @click="test3('abcd', $event)">test3</button>

  <h2>2. 事件修饰符  <!--
    阻止事件的默认行为:.prevent
  -->
  <a href="http://www.baidu.com" @click.prevent="test4">百度一下</a>

   <!--
 事件冒泡
 如何实现 点击inner仅显示inner。需要做到的是:停止事件冒泡 .stop
 -->
 <div style="width: 200px;height: 200px;background: red" @click="test5">
   <div style="width: 100px;height: 100px;background: blue" @click.stop="test6"></div>
 </div>

 <h2>3. 按键修饰符  <!--
  按键抬起时调用  keyup //enter,space...
  -->
  <input type="text" @keyup="test8">
 <input type="text" @keyup.13="test7">
  
 <input type="text" @keyup.enter="test7">

</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
 new Vue({
   el: '#example',
   data: {

   },
   methods: {
     test1(event) {
       alert(event.target.innerHTML)
     },
     test2 (msg) {
       alert(msg)
     },
     test3 (msg, event) {
       alert(msg+'---'+event.target.textContent)
     },

     test4 () {
       alert('点击了链接')
     },

     test5 () {
       alert('out')
     },
     test6 (event) {
       // event.stopPropagation();
       alert('inner')
     },

     test7 (event) {
       console.log(event.keyCode)
       alert(event.target.value)
     },
     test8 (event) {
       // console.log(event.keyCode)
       if(event.keyCode==13){
         alert(event.target.value)
       }

     }
   }
 })
</script>
</body>
</html>

11.2 执行效果

11.2.1 点击绑定监听

image.png

11.2.2 点击prevent事件

image.png

11.2.3 点击防止事件冒泡

点击inner:

image.png

点击按键修饰1:

image.png

点击按键修饰2:

image.png

点击按键修饰3:

image.png

12 vue 表单数据的自动绑定

12.1 代码和笔记

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>08_表单输入绑定</title>
</head>
<body>
<!--
1. 使用v-model(双向数据绑定)自动收集数据
  text/textarea 单行或多行文本
  checkbox 单选
  radio  复选
  select  下拉框
-->
<div id="demo">
  <!-- form通过 submit 取消自动提交 ——阻止默认行为
  -->
  <form action="/xxx" @submit.prevent="handleSubmit">
    <span>用户名:     <input type="text" v-model="username"><br>

    <span>密码:     <input type="password" v-model="pwd"><br>

    <span>性别:     <!-- value 值 跟 定义时对照
  -->
    <input type="radio" id="female" value="女" v-model="sex">
    <label for="female">女</label>
    <input type="radio" id="male" value="男" v-model="sex">
    <label for="male">男</label><br>

    <span>爱好:     <!-- value 值 跟 定义时对照 应该定义时选择数组 []
-->
    <input type="checkbox" id="basket" value="basket" v-model="likes">
    <label for="basket">篮球</label>
    <input type="checkbox" id="foot" value="foot" v-model="likes">
    <label for="foot">足球</label>
    <input type="checkbox" id="pingpang" value="pingpang" v-model="likes">
    <label for="pingpang">乒乓</label><br>

    <span>城市:     <!-- value 值 跟 定义时对照 应该定义时选择数组 []
-->
    <select v-model="cityId">
      <option value="">未选择</option>
      <!-- 记得value前有冒号 -->
      <option :value="city.id" v-for="(city, index) in allCitys" :key="city.id">{{city.name}}</option>
    </select><br>
    <span>介绍:     <textarea rows="10" v-model="info"></textarea><br><br>

    <input type="submit" value="注册">
  </form>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  new Vue({
    el: '#demo',
    data: {
      username: '',
      pwd: '',
      sex: '男', //默认男
      likes: ['foot'], //默认足球被选中
      allCitys: [{id: 1, name: '北京'}, {id: 2, name: '南京'}, {id: 3, name: '深圳'}], //所有城市的列表数组
      cityId: '2',
      info: ''
    },
    methods: {
      handleSubmit () {
        console.log(this.username, this.pwd, this.sex, this.likes, this.cityId, this.info)
        alert('提交注册的ajax请求')
      }
    }
  })
</script>
</body>
</html>

12.2 执行效果

12.2.1 原始效果

image.png

12.2.2 点击注册

image.png

13 vue生命周期

13.1 代码和笔记

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>09_Vue实例_生命周期</title>
</head>
<body>
<!--
三个阶段:
初始化显示--》更新显示--》死亡
每个阶段都会对应声生命周期的回调函数(钩子)
案例:每隔一秒钟改变内容

1. vue对象的生命周期
  1). 初始化显示
    * beforeCreate() 创建前(其实是已经创建好后的准备工作)
    observe data 监视观察 给属性增加set方法监视属性变化
    * created()  已创建
    判断是否有el,如果有,则继续,否则使用vm.$mount(el)
    解析模板语法
    先在内存中做解析替换,界面不变;解析好之后,一次性变化大括号表达式(批量) 这样可以减少更新的次数
    * beforeMount() 挂载前

    * mounted()  已挂载——一般会选择mounted 常用。
  2). 更新状态 this.xxx = value
    * beforeUpdate() 更新前
    重新渲染
    * updated() 已更新
  3). 销毁vue实例: vm.$destory()被调用时
  页面仍然显示,但是没有数据绑定了。
    * beforeDestory()  销毁前  收尾工作 常用。
    * destoryed() 已销毁
2. 常用的生命周期方法
  created()/mounted(): 发送ajax请求, 启动定时器等异步任务
  beforeDestory(): 做收尾工作, 如: 清除定时器
-->

<div id="test">
  <!--当点击按钮时,调用destroyVue方法销毁vm
  -->
  <button @click="destroyVue">destory vue</button>
  <p v-if="isShow">华为云Web前端学习</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  new Vue({
    el: '#test',
    data: {
      isShow: true
    },
    //初始化阶段
    beforeCreate() {
      console.log("beforeCreate()")
    },
    created() {
      console.log("created()")
    },
    beforeMount() {
      console.log("beforeMount()")
    },
    mounted () {  //初始化显示之后立即调用一次 用的最多
      // 执行异步任务  只要是回调函数,就做成箭头函数
      this.intervalId = setInterval(() => {
        console.log('-----')
        this.isShow = !this.isShow //更新数据
      }, 1000)
    },

    //更新阶段,执行N次
    beforeUpdate() {
      console.log("beforeUpdate()")
    },
    updated() {
      console.log("updated()")
    },

    //销毁阶段
    beforeDestroy() { //销毁之前调用一次 用的最多
      console.log('beforeDestroy()')
      // 执行收尾的工作 如果不加则会内存泄露
      //与上面的mounted时的定义一致
      clearInterval(this.intervalId)
    },

    destroyed(){
      console.log("destroyed()")
    },

    methods: {
      destroyVue () {
        this.$destroy()
      }
    }
  })


</script>
</body>
</html>

13.2 执行效果

13.2.1 初始页面:每个一秒钟显示一次

显示:

image.png

不显示:

image.png

13.2.2 日志

反复在beforeUpdate和updated循环

image.png

13.2.3 点了destroy之后

image.png

14 vue动画

14.1 transition动画

14.1.1 代码和笔记

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>10_过渡&动画1</title>
  <style>
    /*指定过渡样式*/
    .xxx-enter-active, .xxx-leave-active {
      /* 持续时间1s opacity */
      transition: opacity 1s
    }
    /*指定隐藏时的样式 进入前和离开后都看不到*/
    .xxx-enter, .xxx-leave-to {
      opacity: 0;
    }

    /* 显示过渡的效果 显示1秒*/
    .move-enter-active {
      transition: all 1s
    }

    /* 隐藏过渡的效果 隐藏3秒*/
    .move-leave-active {
      transition: all 3s
    }

    /* 隐藏时的样式 */
    .move-enter, .move-leave-to {
      opacity: 0;
      /* 向右隐藏 */
      transform: translateX(20px)
    }
  </style>
</head>
<body>
<!--
1. vue动画的理解
  操作css的trasition或animation( vue本身并不生产动画)

  vue会给目标元素添加/移除特定的class
2. 基本过渡动画的编码
  1). 在目标元素外包裹<transition name="xxx">
  2). 定义class样式
    1>. 指定过渡样式: transition
    2>. 指定隐藏时的样式: opacity/其它
3. 过渡的类名
  xxx-enter-active: 指定显示的transition
  xxx-leave-active: 指定隐藏的transition
  xxx-enter: 指定隐藏时的样式

  目标:移动效果,放大缩小的效果
  案例一:渐变显示和消失
  案例二:进入和离开时间不一样。还需要移动

-->



<div id="demo">
  <button @click="isShow = !isShow">Toggle</button>
  <!-- 在P标签的外围加了一个transition标签
  vue会给加一些类名,
  比如 xxx-enter(进入前),xxx-enter-to(进入后),xxx-enter-active(过程中)
  比如 xxx-leave(离开前),xxx-leave-to(进入后),xxx-leave-active(过程中)
 -->
  <transition name="xxx">
    <p v-show="isShow">显示及隐藏的效果  </transition>
</div>

<hr>
<div id="demo2">
  <button @click="isShow = !isShow">Toggle2</button>

  <transition name="move">
    <p v-show="isShow">向右移动消失的效果  </transition>
</div>


<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  new Vue({
    el: '#demo',
    data: {
      isShow: true
    }
  })

  new Vue({
    el: '#demo2',
    data: {
      isShow: true
    }
  })

</script>
</body>
</html>

14.1.2 显示效果

(注:动画无法演示)

image.png

点第一个toggle

image.png

可见已逐渐消失

点第二个toggle

image.png

难得截到了向右漂移的效果。。逐步消失:

image.png

14.2 animation动画

14.2.1 代码和笔记

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>10_过渡&动画2</title>
  <style>
    /* 进入时的动画 */
    .bounce-enter-active {
      animation: bounce-in 1s;
    }

    /* 离开时的动画 */
    .bounce-leave-active {
      animation: bounce-in 1s reverse;
    }

    /* 动画配置 */
    @keyframes bounce-in {
      0% {   /* 0秒时看不见 */
        transform: scale(0);
      }
      50% {  /* 1秒时放大为 1.5倍 */
        transform: scale(1.5);
      }
      100% {  /* 最终还原回原始大小 */
        transform: scale(1);
      }
    }
  </style>
</head>
<body>

<div id="example-2">
  <!--animation的动画效果
  1.首先需要一个transition标签
  2.定义过渡样式transition和隐藏时的样式

  -->
  <button @click="show = !show">放大并还原的动画效果</button>
  <br>
  <transition name="bounce">
    <p v-if="show" style="display: inline-block">Lorem  </transition>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script>
  new Vue({
    el: '#example-2',
    data: {
      show: true
    }
  })
</script>
</body>
</html>

14.2.2 显示效果

原始效果:

image.png

点击后的效果:

image.png

截到了缩小准备消失得小字效果。。

15 vue过滤器

15.1 代码和笔记

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>11_过滤器</title>
</head>
<body>
<!--
1. 理解过滤器
  功能: 对要显示的数据进行“特定格式化”后再显示
  注意: 并没有改变原本的数据, 可是产生新的对应的数据
2. 编码
  1). 定义过滤器
    Vue.filter(filterName, function(value[,arg1,arg2,...]){
      // 进行一定的数据处理
      return newValue
    })
  2). 使用过滤器 管道符
    <div>{{myData | filterName}}</div>
    <div>{{myData | filterName(arg)}}</div>
-->
<!--需求: 对当前时间进行指定格式显示-->
<div id="test">
  显示格式化的日期时间  {{time}}  最完整的: {{time | dateString}}  年月日: {{time | dateString('YYYY-MM-DD')}}  yeartoday {{ time | dateStr('YYYYMMDD')}}  hourtosecond {{ time | dateStr('HHmmss')}}  full {{ time | dateStr()}}</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/moment.js/2.22.1/moment.js"></script>
<script>
  // 定义过滤器 作为函数对象使用。
  Vue.filter('dateString', function (value, format='YYYY-MM-DD HH:mm:ss') {
    //moment库 日期格式化 momentjs.cn
    //使用cdn bootcdn.cn
    return moment(value).format(format);
  })

  Vue.filter('dateStr', function (value,format) {
    //moment库 日期格式化 momentjs.cn
    //使用cdn bootcdn.cn
    return moment(value).format(format || 'YYYY-MM-DD HH:mm:ss');
  })

  new Vue({
    el: '#test',
    data: {
      time: new Date()
    },
    mounted () {
      setInterval(() => {
        this.time = new Date()
      }, 1000)
    }
  })
</script>
</body>
</html>

15.2 执行效果

image.png


16 vue指令和自定义指令

16.1 内置指令

16.1.1 代码和笔记

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>12_指令_内置指令</title>
  <style>
    /* 属性选择器 */
    [v-cloak] {
      display: none
    }
  </style>
</head>
<body>
<!--
常用内置指令
  v:text : 更新元素的 textContent
  v-html : 更新元素的 innerHTML
  v-if : 如果为true, 当前标签才会输出到页面
  v-else: 如果为false, 当前标签才会输出到页面
  v-show : 通过控制display样式来控制显示/隐藏
  v-for : 遍历数组/对象
  v-on : 绑定事件监听, 一般简写为@
  v-bind : 强制绑定解析表达式, 可以省略v-bind,用冒号代替
  v-model : 双向数据绑定
  本次仅讲解这两个:
  ref : 为某个元素注册一个唯一标识, vue对象通过$refs属性访问这个元素对象
  v-cloak : 使用它防止闪现表达式, 与css配合: [v-cloak] { display: none }
-->
<div id="example">
<!--  <p v-text="content">   <!&ndash;p.textContent = content&ndash;>-->
<!--  <p v-html="content">  <!&ndash;p.innerHTML = content&ndash;>-->
  <!--根据ref获得标签的内容 this.$refs.msg得到的是P标签
  模板v-text在解析前有属性,但是在解析之后没有了
  可以利用这点:指令属性在解析前没有,在解析后就能出来。
  -->
<!--  <p ref="msg">abcd-->
<!--  <p ref="content">能显示吗?-->
  <button @click="hint">提示</button>
  <p v-cloak>{{msg}}</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  alert('在vue之前')
  new Vue({
    el: '#example',
    data: {
      msg: 'Zhanghui'
    },
    methods: {
      hint () {
        //如何做到没解析好之前不显示
        alert(this.$refs.content.textContent)
        // alert('innerHTML'+this.$refs.msg.innerHTML)
      }
    }
  })
</script>
</body>
</html>

16.1.2 执行效果

点击前:

image.png


点击后:

image.png

16.2 自定义指令

16.2.1 代码和笔记

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>12_指令_自定义指令</title>
</head>
<body>

<!--
内置指令个数有限,需要特别功能时,可以复用

1. 注册全局指令 对所有对象适用  el是标签所在的element
  Vue.directive('my-directive', function(el, binding){
    el.innerHTML = binding.value.toupperCase()
  })
2. 注册局部指令 仅对一个vue对象适用
  directives : {
    'my-directive' : {
        bind (el, binding) {
          el.innerHTML = binding.value.toupperCase()
        }
    }
  }
3. 使用指令
  v-my-directive='xxx'
-->
<!--
需求: 自定义2个指令
  1. 功能类型于v-text, 但转换为全大写 v-upper-text 定义成全局
  2. 功能类型于v-text, 但转换为全小写 v-lower-text 定义成局部
  指令名:v-去掉之后的,比如v-upper-text的指令名为upper-text
  指令是用来写成标签属性去操作标签的
-->

<div id="test1">
  <p v-upper-text="msg1">  <p v-lower-text="msg1"></div>

<div id="test2">
  <p v-upper-text="msg2">  <p v-lower-text="msg2"></div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  // 注册一个全局指令
  // el: 指令所在的标签对象
  // binding: 包含指令相关数据的容器对象-难点
  Vue.directive('upper-text', function (el, binding) {
    console.log(el, binding)
    //指定el的内容为 相关的值
    el.textContent = binding.value.toUpperCase()
  })
  new Vue({
    el: '#test1',
    data: {
      msg1: "I Love You,Atlas"
    },
    // 注册局部指令,只在test1中有效
    directives: {
      'lower-text'(el, binding) { //ES6的简洁语法,等同于 'lower-text':function(el,binding)..
        console.log(el, binding)
        el.textContent = binding.value.toLowerCase()
      }
    }

  })

  new Vue({
    el: '#test2',
    data: {
      msg2: "I Love You,HiLens"
    }
  })
</script>
</body>
</html>


16.2.2 执行效果

image.png

可见,全局指令全部有效,但是局部指令在test2中无效。

17 vue插件

17.1 代码和笔记

建一个插件js文件

(function (window) {

  //需要向外暴露的一个插件对象
  const MyPlugin = {}
  //插件对象必须有一个install方法,被vue调用
  MyPlugin.install = function (Vue, options) {
    // 1. 添加全局方法或属性 定义一个函数 myGlobalMethod
    Vue.myGlobalMethod = function () {
      console.log('Vue函数对象的myGlobalMethod()')
    }

    // 2. 添加全局资源 自定义指令my-directive
    Vue.directive('my-directive',function (el, binding) {
      el.textContent = 'my-directive----'+binding.value.toUpperCase()
    })

    // 3. 添加实例方法 将实例方法myMethod放到原型上
    Vue.prototype.$myMethod = function () {
      console.log('VUE实例对象的方法 $myMethod()')
    }
  }

  //向外暴露
  window.MyPlugin = MyPlugin
})(window)

调用方式:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>17_插件</title>
</head>
<body>

<div id="test">
  <!-- 使用插件定义的指令 -->
  <p v-my-directive="msg"></div>

<script type="text/javascript" src="../js/vue.js"></script>
<!-- 在进入vue.js后引入自定义插件 -->
<script type="text/javascript" src="vue-myPlugin.js"></script>
<script type="text/javascript">
  // 声明使用插件(安装插件: 调用插件的install())
  Vue.use(MyPlugin) // 内部会调用MyPlugin.install(Vue) 将插件安装上去

  const vm = new Vue({
    el: '#test',
    data: {
      msg: 'Self Def Plugin...'
    }
  })

  //调用全局方法
  Vue.myGlobalMethod()

  //调用实例方法
  vm.$myMethod()

  // new Object()
</script>
</body>
</html>

17.2 执行效果

image.png

可见:插件的全局方法,自定义指令和vue实例vm的方法,都被调用到了。

(全文完,谢谢阅读)


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。