文章目录

1、指令语法

1.methods里面的方法简写:

add:function () {
 console.log("ok")
}
<!--简写后-->
add(){
   this.weight += 3
}

2.v-on(绑定事件)简写:

v-on:click="add()"
<!--简写后-->
@click="add()"

3.v-bind(绑定元素、数据)简写

v-bind:class=''
<!--简写后-->
:class=''

3.v-bind只能实现数据的单向绑定,从data中自动同步到view上
v-model能双向绑定(只有model能双向绑定),但是v-model只能用在表单元素上如input、text、radio、CheckBox、textarea、select等

5.双向数据绑定,能够让我们在修改表单之后,不必自己操作dom元素获取表单元素的值;

4.事件修饰符

  • .stop阻止冒泡
  • .prevent阻止默认事件
  • .capture 添加事件侦听器时使用事件捕获模式
  • .self 只当事件在该元素本身(比如不是子元素)触发时触发回调
  • .once 事件只触发一次

2、在vue中使用样式

2.1、使用class样式

1.数组形式

<h1 :class="['red', 'thin']">这是一个邪恶的H1</h1> 

2.数组中使用三元表达式

<h1 :class="['red', 'thin', isactive?'active':'']">这是一个邪恶的H1</h1>  

3.数组中嵌套对象(常用),active是类名,:右边是属性,如果类名出现-(thin-ok)则需要加引号

<h1 :class="['red', 'thin', {'active': isactive}]">这是一个邪恶的H1</h1>

4.直接使用对象(常用)

<h1 :class="{red:true, italic:true, active:true, thin:true}">这是一个邪恶的H1</h1>

2.2、使用内联样式

1.直接在元素上通过 :style 的形式,书写样式对象,属性和属性值最好都用引号

<h1 :style="{color: 'red', 'font-size': '40px'}">这是一个善良的H1</h1>

2.将样式对象,定义到 data 中,并直接引用到 :style 中

<h1 :style="styleObj">这是一个善良的H1</h1>
<!--如果有两个样式,则使用数组把样式组合-->
<h1 :style="[styleObj,styleObj2]">这是一个善良的H1</h1>

data: {
   styleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }
}

3、v-for循环

3.1 v-for循环数组

<div id="app">
    <ul>
      <li v-for="(item, i) in list">{{ i }} ---------- {{ item }}</li>
    </ul>
  </div>
  
   <script>
      // 创建 Vue 实例,得到 ViewModel
      var vm = new Vue({
        el: '#app',
        data: {
          list: ['嬴政', '李斯', '吕不韦', '赵姬', '赵高']
        },
        methods: {}
      });
    </script>

3.2 v-for循环对象数组

<ul>
        <!--i 是索引,item是遍历每个数组元素-->
      <li v-for="(item, i) in list1">{{ item.id }} ---- {{ item.name }} --- {{ i }}</li>
</ul>

 <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        list1: [
          { id: 1, name: '嬴政' },
          { id: 2, name: '李斯' },
          { id: 3, name: '吕不韦' },
          { id: 4, name: '尉缭子' }
        ]
      },
      methods: {}
    });
  </script>
  <!--结果为-->
    1 ---- 嬴政 --- 0
    2 ---- 李斯 --- 1
    3 ---- 吕不韦 --- 2
    4 ---- 尉缭子 --- 3

3.3 v-for循环对象中的属性

 <ul>
      <li v-for="(val, key, i) in person">{{ val }} --- {{ key }} --- {{ i }}</li>
 </ul>
 
 <script>
     // 创建 Vue 实例,得到 ViewModel
     var vm = new Vue({
       el: '#app',
       data: {
         person: {
           id: 1,
           name: '泥巴巴',
           age: 22,
           gender: '男'
         }
       },
       methods: {}
     });
   </script> 
   <!--结果为-->
   1 --- id --- 0
   泥巴巴 --- name --- 1
   22 --- age --- 2
   男 --- gender --- 3
   

4、v-if和v-show的使用

v-if和v-show只有一个作用,就是根据指定的标识符,切换元素的显示和隐藏状态
v-if 是实时的创建或移除元素,从而达到元素的显示和隐藏

v-show 是通过为元素 添加或移除 display:none 来实现隐藏和显示的
区别:
如果元素需要经常的切换显示和隐藏的状态,此时,使用 v-show 更合适一些;
如果元素被创建出来之后,可能不会进行状态的切换,此时,适合使用 v-if

<body>
<input type="button" value="toggle" @click="flag=!flag">
<h3 v-if="flag">哈哈哈</h3> //如果flag为true则哈哈哈不会显示
<h6 v-show="flag">12345</h6>
</body>

 <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: true
      }
      
    });
  </script>

4、过滤器

4.2全局过滤器

作用是在渲染页面时,使用过滤器的函数。Vue.js允许你自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:mustache 插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示;

注意:过滤器并不会修改原数据,只是在展示数据的时候做了一层包装而已

语法:Vue.filter(‘过滤器被调用时的名称’,过滤器的处理函数)

<body>
<!--  在调用过滤器的时候, 需要使用 | 来调用, | 叫做管道符  -->
   <td>{{ item.ctime | formatDate }}</td>
   <!--调用有参数的过滤器-->
   <td>{{ item.ctime | formatDate | addStr('----', '====')}}</td>
</body>

<script >
// 自定义一个 全局的 过滤器
    // Vue.filter('过滤器将来被调用时候的名称', 过滤器的处理函数)
    // 注意:过滤器的处理函数中, 第一个形参,作用已经被规定死了,永远是 管道符 前面的值
    Vue.filter('formatDate', function (data) {
       console.log('过滤器被调用了')
       return data + '~~~'
    })
    
    //定义要要传参数的过滤器
    // 如果要为过滤器传递参数,则 传递的参数,只能在 第二个形参的位置开始接收
        Vue.filter('addStr', function (data, str, str2) {
          return data + str + str2
        })
</script>

4.2私有过滤器

私有过滤器写在vm实例对象中,添加一个filter属性即可

<script >
    var vm2 = new Vue({
      data: {
        msg: '纯洁,纯洁,纯洁,纯洁'
      },
      methods: {}, // 事件处理函数,一些方法
      filters: { // 当前实例私有的过滤器
        addStr1(data) {
          return data + '~~~~'
        },
        // 如果全局过滤器和私有过滤器重名了,则会就近原则调用过滤器
        strFormat(data) { // vm2 的私有过滤器,会在给定字符串的后面,添加一串 ===== 
          return data + '========'
        }
      }
    })
</script>

5、自定义指令

5.1 全局自定义指令

语法:Vue.directive(‘指令名’,{对象/处理函数})

<body>
//调用
<input type="text" v-model="keywords" @change="searchByName" v-focus>
</body>

<script >
Vue.directive('focus',{
    //如果要操作元素的样式, 写到 bind 就行了
    //bind:当指令绑定到的元素,被Vue实例解析的时候,就会立即执行bind函数
    bind:function(el) {  // 参数列表中的第一个参数,永远是el,表示被绑定指令的那个元素
      //一般元素的样式写在bind中
      el.style.color='red'
    }
    //inserted:当指令绑定到的元素,被插入到文档的父节点时候,调用 inserted 函数
    inserted:function(el) {
       //一般元素的行为或事件写在inserted中
       el.focus()
    }
}
    
)
</script>

5.2 binding.value参数

<body>
<th v-color="'blue'">操作</th> //显示蓝色
<span v-color>按照品牌名称检索:</span> //显示红色
</body>
<script >
//定义一个color的指令,谁调用了谁就变颜色
Vue.directive('color', {
      bind(el, binding) { //el是绑定的那个元素,binding是绑定的那个元素里v-color="参数"中的参数
        //这里的binding.value是blue
        el.style.color = binding.value || 'red'  //如果binding.value有传入参数则不用管后面的,如果没有则是red
      },
      inserted(el) { }
    })

</script>

5.3 私有自定义指令

<body>
<th v-bold="200">操作</th>
</body>
<script >
var vm = new Vue({
directives: { // 自定义指令区域
        bold: { // 让指定元素字体加粗的指令
          bind(el, binding) {
            el.style.fontWeight = binding.value
          },
          inserted(el) { }
        },
        
      }
})

</script>

6、按键修饰符

<body>
<!--现在要在文本框内输入文本后按下enter就能添加到列表-->
<input type="text" v-model="name" @keyup.enter="add">
</body>
<script >
var vm = new Vue({
methods:{
    add(){
        
    }
}
})
</script>

为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

7、vue生命周期函数

<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        msg: '123'
      },
      methods: {
        show() {
          console.log('show 方法被调用了')
        }
      },
      beforeCreate() { // 这是我们遇到的第一个生命周期函数【创建阶段】
        // console.log(this.msg)
        // this.show()
      },
      created() { // 这是我们遇到的第二个生命周期函数  【创建阶段】
        // console.log(this.msg)
        // this.show()
      },
      beforeMount() { // 创建阶段的第三个 生命周期函数  表示,即将挂载
        // const ele = document.getElementById('myh3')
        // console.log(ele.innerHTML)
      },
      mounted() {  // 创建阶段的第 4 个生命周期函数, 表示 页面已经完成了渲染,同时,mounted 函数的执行,标志着 创建阶段的结束,从此以后,Vue 实例,就从创建阶段,进入到运行阶段;
        /* const ele = document.getElementById('myh3')
        console.log(ele.innerHTML) */
      },
      // -------------------之前的是创建/编译阶段,后面的是运行阶段--------------------------
      beforeUpdate() { // 更新之前
        /* const ele = document.getElementById('myh3')
        console.log(ele.innerHTML) */
      },
      updated() { // 更新之后
        const ele = document.getElementById('myh3')
        console.log(ele.innerHTML)
      }
    });
  </script>

8、使用vue-resource请求数据

8.1 get请求

<!--先导入包-->
<script src="./lib/vue-2.5.9.js"></script>
<!-- vue-resource 只能在 vue 的后面导入  -->
<script src="./lib/vue-resource-1.3.4.js"></script>

<body>
 <input type="button" value="Get请求" @click="getInfo">
</body>

<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
          //方法一
        /* getInfo() { // get方式请求数据
          this.$http.get('http://39.106.32.91:3000/api/getlunbo').then(function (data) {
            console.log(data.body) //输出的是promise对象的body值
          })
        } */
           //方法二
        async getInfo() {
          const { body } = await this.$http.get('http://39.106.32.91:3000/api/getlunbo')
          console.log(body) //输出的是promise对象的body值。
        }
      }
    });
  </script>

8.2 post请求

<body>
<input type="button" value="Post请求" @click="postInfo">
</body>

<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        async postInfo() {
        //post(url,{对象})把这个对象发送到这个url地址
          const { body } = await this.$http.post('http://39.106.32.91:3000/api/post', { name: '高婆婆', age: 22, gender: '妖人' })
          console.log(body)
          //传入了什么数据就输出了什么数据 { name: '高婆婆', age: 22, gender: '妖人' }
        }
      }
    });
  </script>

8.3 jsonp请求

<body>
<input type="button" value="Post请求" @click="jsonpInfo">
</body>

<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        async jsonpInfo() {
          const { body } = await this.$http.jsonp('http://39.106.32.91:3000/api/jsonp')
          console.log(body)
        }
      }
    });
  </script>

9、使用axios结合vue发出请求

Ajaxs使用总结:
使用jQuery需要导入jQuery,使用Vue导入Vue,两个都用,自己原生态实现
三步曲:
1.编写对应处理的Controller ,返回消息或者字符串或者json格式的数据;
2.编写ajax请求
1. url : Controller请求
2. data :键值对
3. success:回调函数
3.给Ajax绑定事件,点击.click, 失去焦点onblur,键盘弹起keyup

<!--要先导入axios包-->
<script src="./lib/vue-2.5.9.js"></script>
<script src="./lib/axios-v0.17.1.js"></script>
<body>
<input type="button" value="get请求" @click="getInfo">
<input type="button" value="post请求" @click="postInfo">
</body>
<script >

// 把 axios 挂载到 Vue 构造函数的原型上
    Vue.prototype.$http = axios
    
var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        async getInfo() {
          // this.$http.get()
          // 使用axios的get方法
          /* const { data } = await axios.get('http://39.106.32.91:3000/api/getlunbo')
          console.log(data) */
            
          // 使用this.$http.get这个方式需要把axios挂载到vue构造函数的原型上
          const { data } = await this.$http.get('http://39.106.32.91:3000/api/getlunbo')
          console.log(data)
        },

        async postInfo() {
          const { data } = await this.$http.post('http://39.106.32.91:3000/api/post', { name: 'zs' })
          console.log(data)
        }
      }
    });
    
</script>

ajax的跨域问题:

  • 由于浏览器的安全性限制,不允许AJAX访问协议不同、域名不同、端口号不同的数据接口,
    浏览器认为这种访问不安全;
  • 解决办法:可以通过动态创建script标签的形式,把script标签的src属性,指向数据接口的地址,因为script标签不存在跨域限制,这种数据获取方式,称作JSONP(注意:根据JSONP的实现原理,知晓,JSONP只支持Get请求);
  • 具体实现过程
    • 先在客户端定义一个回调方法,预定义对数据的操作;
    • 再把这个回调方法的名称,通过URL传参的形式,提交到服务器的数据接口;
    • 服务器数据接口组织好要发送给客户端的数据,再拿着客户端传递过来的回调方法名称,拼接出一个调用这个方法的字符串,发送给客户端去解析执行;
    • 客户端拿到服务器返回的字符串之后,当作Script脚本去解析执行,这样就能够拿到JSONP的数据了;

11、vue的动画

11.1 入场和出场渐变动画效果

  1. Vue把一个完整的动画,拆分成了两部分入场动画和出场动画
  2. 入场动画中,包含两个时间点,分别是进入之前(v-enter)和进入之后(v-enter-to)
  3. v-enter 表示动画入场之前的起始状态,比如:透明度为0,横向偏移量为50px
  4. v-enter-to 表示画入场完成之后的终止状态,比如:透明度为 1,横向偏移量为0px
  5. v-enter-active 表示入场动画的时间段,在这里,可以规定动画的时长、还有一些相关的动画效果ease
  6. v-leave同理,v-enter和v-leave-to的样式是一样的,v-enter-active和v-leave-active的样式一样
<style>
    .v-enter, 
    .v-leave-to {
      opacity: 0; //透明度为0
      transform: translateX(100px); //偏移量为100px
    }

    .v-enter-active,
    .v-leave-active {
      transition: all 0.5s ease; //all:所有样式都变化过渡,0.5s,效果为ease渐变
    }

    h3 {
      opacity: 0.5;
      transform: translateX(40px);
    }
</style>
<body>
<input type="button" value="Toggle" @click="flag=!flag">
 <!-- 1. 把要实现动画的元素,使用 transition 元素包裹起来 -->
 <!-- 2. 要实现动画的元素,必须使用 v-if 或 v-show 来进行控制 -->
    <transition>
      <h3 v-show="flag">这是一个要使用动画控制的元素</h3>
    </transition>
</body>
<script >
   // 创建 Vue 实例,得到 ViewModel
   var vm = new Vue({
     el: '#app',
     data: {
       flag: false // 显示的状态
     },
     methods: {}
   });
</script>

11.2 使用现成的css动画库

<!--① 首先要导入css动画库Animate.css-->
<head>
<link rel="stylesheet" href="./lib/animate.css">
<script src="./lib/vue-2.5.9.js"></script>
</head>

<body>
<div id="app">
    <input type="button" value="Toggle" @click="flag=!flag">
    <!--② transition标签中有个enter-active-class类,这个类中写css库中的动画名称,想要库中哪种效果就写哪种效果-->
    <!--入场效果是enter-active-class,出场是leave-active-class-->
    <transition enter-active-class="bounceInDown" leave-active-class="bounceOutDown">
      <!--③ 还需要在想要实现效果的标签中加个class="animated"-->
      <h3 v-show="flag" class="animated">哈哈哈哈哈哈哈</h3>
    </transition>
  </div>
</body>

11.3 多个元素的动画过渡-列表的动画过渡

看例子

11.4 定义两个动画时的标签名

如果要定义两个动画,则第二个动画的标签可以写成.fade-enter,.fade-leave-to。。。
和v-enter…区别开来

  <style>
    .v-enter,
    .v-leave-to {
      opacity: 0;
      transform: translateX(100px);
    }

    .v-enter-active,
    .v-leave-active {
      transition: all 0.4s ease;
    }

     /*第二个动画样式*/
    .fade-enter,
    .fade-leave-to {
      opacity: 0;
      transform: translateY(100px);
    }

    .fade-enter-active,
    .fade-leave-active {
      transition: all 1s ease;
    }
  </style>
  <body>
   <input type="button" value="Toggle" @click="flag=!flag">
      <transition>
        <h3 v-show="flag">111111111</h3>
      </transition>
  
      <hr>
        <!--第二个动画-->
      <input type="button" value="Toggle2" @click="flag2=!flag2">
      <transition name="fade">
        <h3 v-show="flag2">22222222</h3>
      </transition>
</body>

12、组件component

const vm = new Vue({
        el: '#app',
        data: {},
        methods: {
          getList() {
          }
        },
        filters: {},
        directives: {},
        created() { // 表示 data 数据 和 methods 方法都已经可用了
          this.getList()
        },
        mounted() { // 表示 内存中渲染好的 DOM 树,已经挂载到了真实的页面中;
          //在网页中,有一些 第三方的 插件,需要初始化;  
          // 使用 Jquery 封装出来的框架分为两部分: UI结构 JS代码 
          // 因此: 一些第三方的插件,如果要结合Vue来使用,而且,这个插件需要手动初始化JS逻辑,此时,必须放到 mounted ,否则,可能无法出现预期效果;
        }
      })

12.1 全局组件

vue的组件也是vue的一种特殊的实例

1. 创建全局组件的第一种方式:

    <script >
    const com1 = Vue.extend({
      template: '<h1>这是创建的第一个全局组件</h1>' // template 属性,表示这个组件的 UI 代码解构
    })
    // 使用 1. Vue.component 向全局注册一个组件
    // 语法:Vue.component('组件的名称', 组件的构造函数)
    Vue.component('mycom1', com1) //这个com1就是个构造函数,前面是组件的命名(命名不能大写)
    </script>
    <body>
    <!-- 2. 创建要控制的区域 -->
      <div id="app">
        <!--调用-->
        <!--如何引入一个全局的Vue组件呢? 直接把组件的名称,以标签的形式,放到页面上就好了! -->
        <mycom1></mycom1>
     </div>
</body>

2. 创建全局组件的第二种方式:

<script>
    // 定义全局的组件
    // Vue.component 的第二个参数,既接收 一个组件的构造函数,同时也接受 一个对象
    Vue.component('mycom2',{
        template:'<h2>这是直接用Vue.component创建出来的组件</h2>'
        // 1. template 属性中,不能单独放一段文本,必须用标签包裹起来;
        // 2. 如果在 template 属性中,想要放多个元素了,那么,在这些元素外,必须有唯一的一个根元素进行包裹;
    })
</script>
<body>
    <!--调用-->
    <mycom2></mycom2>
</body>

3. 创建全局组件的第三种方式:

<body>
<!-- 定义一个 template 标签元素  -->
  <!-- ② 使用 Vue 提供的 template 标签,可以定义组件的UI模板解构 -->
  <template id="tmpl">
    <div>
       <!--如果外面没有div包围的话,h3只能有一个,因为根标签只能有一个-->
      <h3>哈哈,这是在外界定义的组件UI解构</h3>
      <h3>我是来捣乱的</h3>
    </div>
  </template>
  <!--③ 使用组件-->
  <div id="app">
      <mycom3></mycom3>
  </div>
</body>

<script >
// ① 这是定义的全局组件
    Vue.component('mycom3', {
      template: '#tmpl'
    })
</script>

12.2 私有组件

<body>
<!--使用组件-->
<div id="app">
      <mycom4></mycom4>
    </div>
</body>
<script >
// 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      components: { // 定义实例中私有组件的   组件的名称   和组件的 解构
        'mycom4': {
          template: '<h6>这是定义的私有组件</h6>'
        }
      }
    });
</script>

12.3 在组件中定义自己的私有data和methods

<script>
Vue.component('mycom', {
      template: '<h3 @click="show">这是自定义的全局组件:{{ msg }}</h3>',
      data: function () { // 在组件中,可以有自己的私有数据,但是组件的data必须是一个function,并且内部return一个数据对象
        return {
          msg: '哈哈哈'
        }
      },
      methods: { // 定义组件的私有方法
        show() {
          console.log('触发了组件的私有show方法!')
        }
      }
    })
</script>

12.4 父组件为子组件传递数据(通过属性绑定)

步骤:
1.把要传递给子组件的数据,作为自定义属性,通过 v-bind: 绑定到子组件身上:

2.在子组件中,不能直接使用父组件传递过来的数据,需要先使用props 数组来接收一下:
props: [‘msg123’]
3.注意:在接收父组件传递过来的 props的时候,接收的名称,一定要和父组件传递过来的自定义属性,名称保持一致!

<body>
<div id="app">
    <!-- 父组件如果想要给子组件传递数据,则需要使用属性绑定的形式 -->
    <!-- 这样,子组件身上的自定义数据,就是你要传递给子组件的数据 -->
    <com1 :msg123="parentMsg"></com1>
  </div>
</body>

<script>
    var vm = new Vue({
      el: '#app',
      data: {
        parentMsg: '哈哈,你是想笑死我,然后好继承我的蚂蚁花呗吗?' //父组件的数据
      },
      methods: {},
      components: { // 定义私有组件
        'com1': { // 在Vue中,默认,子组件无法直接获取父组件中的数据
          template: `<div>
            <h3>这是子组件中的标题 {{ msg123 }}</h3>
          </div>`,
          props: ['msg123'] // 在Vue中,只有props是数组,其它带 s 后缀的属性都是 对象
        }
      }
    });
  </script>

12.5 父组件为子组件传递对象

<body>
<div id="app">
    <com1 :msgobj="msgObj"></com1>
  </div>
</body>
<script>
    var vm = new Vue({
      el: '#app',
      data: {
        msgObj: {
          address: '北京',
          location: '顺义····马坡南'
        }
      },
      components: {
        'com1': {
          template: '<h3>哈哈 {{ JSON.stringify(msgobj) }}</h3>', //json.stringify方法:将JavaScript值转换为JSON字符串
          props: ['msgobj']
        }
      }
    });
  </script>

12.6 父组件为子组件传递方法

<body>
<div id="app">
    <!-- 1. 如果要向子组件传递 data 中的数据,则使用属性绑定的形式 v-bind: -->
    <!-- 2. 如果要向子组件传递 methods 中的方法,则使用事件绑定的形式 v-on: -->
    <com1 @func1="show"></com1>
  </div>
</body>
 <script>
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        show() {
          console.log('有人调用了父组件中的show方法')
        }
      },
      components: { // 定义子组件
        'com1': {
          template: `<div>
            // 当点击子组件的按钮时候,调用一下父组件传递过来的 func 方法
            <input type="button" value="这是子组件的按钮" @click="btnClick" />
          </div>`,
          methods: {
            btnClick() {
              // console.log('ok')
              // 调用一下父组件传递过来的func方法,emit英文原意为发射, 在计算机中,引申为触发
              this.$emit('func1')
            }
          }
        }
      }
    });
  </script>

13、在vue中$refs的使用

13.1 用ref属性调用标签得到标签的内容

这个属性可以不用操作dom就能获取标签的内容

<body>
    <!--在标签中加个ref属性,并且为他命名,就可以被调用了-->
    <h3 ref="myh3">{{ msg }}</h3>
</body>
<script >
    var vm = new Vue({
          el: '#app',
          data: {
            msg: '000'
          },
          methods: {
            getInfo() { // 点击按钮,获取 h3 中的文本内容
              //操作dom来获取标签文本内容
              console.log(document.getElementById('myh3').innerHTML)
              // 使用ref属性来获取文本内容
              console.log(this.$refs.myh3.innerHTML)
            }
          }
        });
</script>

13.2 用ref属性调用组件的私有数据和方法

<body>
    <div id="app">
        <input type="button" value="获取页面上的组件" @click="getCom">
        <com1 ref="mycom"></com1>
      </div>
</body>
<script>
    Vue.component('com1', {
      template: '<h3>这是一个小组件 {{ msg }}</h3>',
      data: function () { // 子组件的私有数据
        return {
          msg: 'ok'
        }
      },
      methods: { // 子组件的方法
        show() {
          console.log('有人调用了子组件的方法')
        }
      }
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        getCom() { //点击按钮修改组件的数据和调用组件的方法
          // 修改 子组件上的数据
          // this.$refs.mycom.msg = '123'
          // 调用子组件中的方法
          // this.$refs.mycom.show()
        }
      }
    });
  </script>

14、在Vue组件中data和props的区别

  1. data 在组件中,要被定义成function并返回一个对象
  2. props 在组件中,要被定义成数组,其中,数组的值都是字符串名,表示父组件传递过来的数据;
  3. props 的数据,不要直接拿来修改,如果想要修改,必须在data上重新定义一个属性,然后把属性的值从this.props拿过来;

data 上的数据,都是组件自己私有的, data 上的数据,都是可读可写的
props 数据,都是外界传递过来的数据, props 中的数据只能读取,不能重新写入

15、路由

  1. 对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源;

  2. 对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现;

  3. 在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由(区别于后端路由);

  4. 前端的路由:就是根据不同的Hash地址,在页面上展示不同的前端组件;

15.1 URL地址中的#

常用的方法有:

  1. window.location.hash: 读取#值。在读取时,可以用来判断网页状态是否改变;写入时,则会在网页不重载的前提下,创造一条新的访问历史记录
  2. onhashchange事件:当#改变时,就会触发这个事件。可以在这个事件后面写个函数,让点击这个#时触发函数
<body>
  <!-- hash # 不会刷新页面,也不会发起新的HTTP请求, 只是实现客户端页面的定位的 -->
  <!-- # 可以修改浏览器端的访问历史纪录 -->
  <a href="#/a">a</a>
  <a href="#/b">b</a>
  <a href="#/c">c</a>

  <script>
    window.onhashchange = function () {
      // console.log('Hash被改变了') 
      console.log(location.hash) //点击哪个a链接,就输出哪个链接的hash值(例如输出#/a)
    }
  </script>
</body>

15.2 v-router的使用

看例子

15.3 路由传参1——获取query形式传递的参数

<body>
    <div id="app">
        <!--1.参数以query形式传递-->
        <!--在需要传输的组件名字后面加个?传入数据名字和数据值-->
        <!--也可以在网页的网址后面加个?id=10-->
        <router-link to="/login?id=10">登录</router-link>
        <router-view></router-view>
</div>
</body>
<script >
    const login = { // 组件也有自己的生命周期函数,这些函数,和 vm 实例的生命周期函数一致
          // 2. 获取参数
          template: '<h3>登录组件 --- {{ $route.query.id }}</h3>',  //这里显示的$route.query.id为10
          created() { // 当 login 组件中 data 和 methods 初始化完毕后,调用 created
            console.log(this.$route.query.id) //$route.query属性是存放输入的数据,id是输入的数据名
          }
        }
</script>

15.4 路由传参2——获取params形式传递的参数

<body>
    <div id="app">
        <!--2.params形式传递的参数-->
        <router-link to="/login/10/zs">登录</router-link>
</div>
</body>
<script >
    const login = {
          // 3. 获取参数
          // $route.params是存放的参数位置
          template: '<h3>登录组件 --- {{ $route.params.id }} --- {{ $route.params.name }}</h3>',
          created() {
            console.log(this)
          }
        }
        
     const router = new VueRouter({
           routes: [ 
               // 1. 定义参数的传递形式和参数名称
             { path: '/login/:id/:name', component: login },
           ],
         })
</script>

15.5 路由传参3——使用props获取参数(vue的新版本才有)

<body>
    <div id="app">
        <!--2.传输参数-->
        <router-link to="/login/10/zs">登录</router-link>
</div>
</body>
<script >
    const login = {
          //3. 在props中写入要用的数据名
          props: ['id', 'name'],
          //4. 直接输入数据名就能获取该数据
          template: '<h3>登录组件 --- {{ id }} --- {{ name }}</h3>',
          }
        }
        
     const router = new VueRouter({
           routes: [ 
               // 1. 定义参数的传递形式和加个props属性为true
             { path: '/login/:id/:name', component: login, props: true },
           ],
         })
</script>

15.6 路由的嵌套——children属性

看例子

15.7 命名视图

当需要把组件在页面布局的时候,需要在创建路由对象的路由规则那里,把每个组件命名,然后再用这些命名来设置布局样式
看例子

16、watch属性

  1. 表示监听指定数据的改变
  2. 使用 watch,可以去监听虚拟的数据,比如:监听 URL 地址的改变(看例子)
  3. 适合监听单个的、虚拟数据的变化,然后做对应的操作
  4. 语法:‘键是要监听的数据’: 数据变化时候的处理函数
watch: { 
      'firstname': function (newval, oldval) { //newval表示新的数据,oldval表示旧的数据
        console.log(newval + ' ----- ' + oldval)
        this.fullname = newval + '-' + this.lastname
      },

17、computed属性

作用:计算属性的值,能监听属性的值的改变
computed的方法里面有个get()和set()方法

<body>
    <!--输入firstname和lastname,在fullname的文本框中显示-->
    firstname:
        <input type="text" v-model="firstname"> + lastname:
        <input type="text" v-model="lastname"> = fullname:
        <input type="text" v-model="fullname"> 
        <!--虽然这个fullname是个function,但是可以看做一个属性来用v-model绑定-->
</body>
<script >
    var vm = new Vue({
          el: '#app',
          data: {
            firstname: '',
            lastname: ''
          },
          methods: {},
          computed: { // 计算属性区域
            'fullname': function () { // 这个 fullname 就是就是计算属性,在页面中,使用计算属性的时候,永远把它当作普通的属性来使用
              // 只要 计算属性的 function中,所依赖的任何数据发生变化了,则会触发计算属性的重新求值
              // 计算属性的值,如果被第一计算后,没有发生过变化,则会把第一次的值,缓存起来,供后续使用,这样能够提高性能
              console.log('ok')
              return this.firstname + '-' + this.lastname
            }
          }
        });
</script>

18、watch、computed和methods之间的对比

  1. computed属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。虽然是个方法,但主要当作属性来使用;
  2. methods方法表示一个具体的操作,主要书写业务逻辑;
  3. watch一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是computed和methods的结合体;

19、webpack的使用

19.1 使用webpack解析打包js文件

  • webpack 是前端项目的构建工具,将来,我们开发的项目,如果想要提高维护性和可控制性的话,尽量选择 webpack 进行构建;
  • webpack 非常适合与单页面应用程序结合使用;不太适合与多页面的普通网站结合使用;
  • 项目中使用 webpack 有什么好处:
    • 能够处理静态资源的 依赖关系;
    • 能够优化项目代码,比如:压缩合并文件,把图片转为base64编码格式;
    • 能够把高级的语法转为低级的语法;
    • webpack 能够转换一些模板文件; .vue
  • 根据官网的图片介绍webpack打包的过程

一般网页中会引入很多静态资源(.js或者.vue那些包),这时候会出现加载慢或者出现静态资源的依赖关系问题。这个时候就可以用到webpack来解决这些问题

webpack的功能

  • 学习Webpack要帮我们压缩、合并常见的静态资源文件;
  • 处理文件的前后依赖关系;
    • webpack如何处理这些依赖关系;
    • webpack内部实现了模块化的机制;(实现模块化的方式,和 Node 中差不多,也是创建了一个模块包装器,把所有的代码都包装起来;)
  • webpack-dev-server:作用帮我们实现在开发阶段中的实时打包编译和刷新浏览器;
  • html-webpack-plugin:把HTML首页自动托管到内存中,自动把打包好的bundle.js路径,以 script 标签 注入到页面中;

webpack安装的两种方式

  • 可以全局安装webpack, 运行 cnpm i webpack -g 全局安装一下webpack;
  • 也可以在项目中安装 webpack, 运行cnpm i webpack -D 安装到项目开发依赖即可;

webpack的使用步骤

  1. 在html文件中不再使用这种导包形式。这样减少了加载慢的现象,实现了模块化。
    在main.js中导包:
    • 导入Jquery:import $ from ‘jquery’
    • 导入css:import ‘…/css/index.css’
      (由于这种导包形式是ES6新特性,目前的Chrome不支持,所以需要用webpack底层将这些高级语法转换成低级语法)
  2. 在控制台运行’ webpack ./src/main.js ./dist/bundle.js ’
    • 第一个路径是要处理的文件,即主要使用的js文件
    • 第二个路径是处理完毕后,要输出的文件。在网页中,只使用处理好的这个文件
  3. 如果想要在控制台直接运行 ‘webpack’ 命令生成文件的话,需要把js内容写在webpack.config.js文件中(在根目录创建)
    在这个文件中写:
const path = require('path')
// 注意: 这里使用Node中的语法,向外暴露了一个配置对象
// 因为 webpack 这个构建工具,底层就是使用 Node.js 开发出来的
module.exports = {
  entry: path.join(__dirname, './src/main.js'),  // 指定要处理的JS文件路径
  output: { // 指定输出文件的配置
    path: path.join(__dirname, './dist'), // 指定输出文件的存放路径
    filename: 'bundle.js' // 指定输出文件的名称
  }
  1. 在html导入这个bundle.js文件的时候,相对路径要搞清楚!!
    • “…/”表示上一级目录开始
    • “./”表示当前同级目录开始
    • “/”表示根目录开始。

19.2 使用webpack-dev-server工具实现实时编译

  1. 使用 webpack-dev-server 这个工具,能够提供类似于 nodemon 的功能,实时监听项目改变,并自定编译项目代码
  2. webpack-dev-server安装时要求webpack在项目里也安装。(全局安装不算,要重新在项目里安装)
  3. 安装这个工具 cnpm i webpack webpack-dev-server -D
  4. 需要打开package.json这个配置文件,找到 scripts 节点,在其中,新增一个dev脚本命令:"scripts": {"dev": "webpack-dev-server"},
  5. 运行npm run dev命令,去执行 dev脚本,启动webpack-dev-server这个实时构建编译的服务器;
  6. 注意:webpack-dev-server打包出来的 bundle.js 并没有存放到实际的物理磁盘,而是托管到了内存中!托管的路径是项目的根目录,所以,在html文件引用的时候,script 标签的路径应该这样写:<script src="/bundle.js"></script>

19.3 使用html-webpack-plugin插件配置启动index.html页面

  1. 这个插件的作用:
    • 能够根据给定的页面路径,在内存中生成一个一模一样的页面;
    • 能够在内存中生成的页面中,自动把 打包好的 bundle.js 文件,注入为一个 script 标签!
  2. 如何配置插件:先运行cnpm i html-webpack-plugin -D安装到本地开发依赖
  3. 在webpack.config.js中,导入这个插件: const htmlWebpackPlugin = require('html-webpack-plugin')
  4. 在webpack.config.js的配置对象中,新增一个 plugins 插件节点:
plugins: [ // 插件的数组
     new htmlWebpackPlugin({ // 创建一个把HTML首页托管到内存中的插件
     template: path.join(__dirname, './src/index.html'), //  要把哪个HTML页面,作为模板,复制一份托管到内存中
     filename: 'index.html' // 指定,将来在内存中复制出来的页面,名称叫做 index.html
     })
 ]

19.4 使用webpack处理css文件

默认情况下:webpack只能默认打包处理后缀名是.js 的文件,无法处理其它后缀名的文件;
如果想要 使用 webpack打包处理非JS类型的文件,那么,需要在项目中配置合适的loader【You may need an appropriate loader to handle this file type.】

使用步骤

  1. 如果想要处理 .css 后缀名的文件,需要安装并配置两个合适的loader【style-loader和css-loader】
    命令为npm i style-loader css-loader --D
  2. 在在webpack.config.js的配置对象中,添加一个module节点,并在module节点下,新增一个rules数组,表示非JS文件的匹配规则:
module: { // 用来配置 非JS文件对应的loader的
  rules: [ // 就是这些 非 JS 文件 和 loader 之间的对应关系
    { test: /\.css$/, use: ['style-loader', 'css-loader'] } // 创建处理 css 文件的 loader 匹配规则
    //前面的正则表达式意思:要匹配的哪种格式。后面的use是用哪些loader加载器处理
 ]
 }
  1. main.js导入写好的css样式:import './index.css'
  • 如果要处理.less 后缀名的文件,需要安装并配置 less-loader。less【less是less-loader的内置依赖项,不需要把less显示的配置到loader规则中】
  • 如果要处理.scss 的文件,需要安装并配置 sass-loader和node-sass【其中,node-sass是sass-loader的内置依赖项】
  • 如果要处理样式表中的图片路径(需要用到url路径的),则需要安装并配置url-loader和file-loader【file-loader是url-loader的内置依赖项】
    * 配置代码:
    module: { // 用来配置 非JS文件对应的loader的
      rules: [ // 就是这些 非 JS 文件 和 loader 之间的对应关系
        { test: /\.jpg|png|gif|bmp$/, use: 'url-loader' } // 配置处理样式表中图片的 loader规则
        //前面的正则表达式意思:要匹配的哪种格式。后面的use是用哪些loader加载器处理
     ]
    

19.5使用webpack处理css文件的路径(如jpg、png等路径)

使用步骤

  1. 运行cnpm i url-loader file-loader -D
  2. 添加配置规则:{ test: /\.jpg|png|gif|bmp$/, use: 'url-loader' }
  3. 如果想要限制什么图片被转码,什么图片不被转码,这时候,可以为 url-loader 提供 limit配置参数;只有小于给定值的图片,才会被转码成base64;limit 的单位是Byte字节
  4. url-loader还有第二个配置参数,叫做 name
    • [name] 表示原来的名字
    • [ext] 表示原后缀名
    • [hash:长度] 表示取Hash值的前几位(总长度是 32 位字符串)
参数解释:
{ test: /\.jpg|png|gif|bmp$/, use: 'url-loader?limit=7631&name=[hash:8]-[name].[ext]' }, // 配置 处理 样式表中图片的 loader规则
      // 可以使用?给 url-loader传递参数,其中,有一个固定的参数,叫做 limit,表示图片的大小,需要给定一个 数值;
      // limit 给定的这个数值,是 图片的大小,单位是 Byte(字节)
      // 如果指定了 limit 参数,则只有图片的大小,小于给定的 值时候,才会转为base64格式的图片;否则,就不转换;

19.6 使用babel处理ES6高级语法(即通过这个编译器把所有低级语法转换为高级)

webpack只能转换一些高级语法,如果要使用更多的高级语法,则要使用babel编译器来处理

使用步骤

  1. 安装两套babel相关的包:

    • 运行 cnpm i babel-core babel-loader babel-plugin-transform-runtime -D
    • 运行 cnpm i babel-preset-env babel-preset-stage-0 -D
  2. 打开webpack.config.js配置文件,添加babel的loader配置项:

// 添加转换JS文件的loader,
// 其中,必须把 node_modules 目录设置为 排除项,这样,在打包的时候,会忽略node_modules 目录下的所有JS文件;否则项目运行不起来!
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
  1. 在项目的根目录中,创建一个.babelrc的配置文件,将来,babel-loader在执行的时候,会读取并使用这个配置文件:
{
 "plugins": ["transform-runtime"],
 "presets": ["env", "stage-0"]
 }
Logo

前往低代码交流专区

更多推荐