06 day2-Vue.js 黑马全家桶笔记

目录

  • (四)生命周期
  • (五)数组
    • (1)数组变异方法
    • (2)替换数组
    • (3)动态数组响应式数据
  • (六)组件
    • (1)组件注册
      • 1.1 使用 Vue.extend 配合 Vue.component 方法
      • 1.2 直接使用 Vue.component 方法
      • 1.3 定义在外面
      • 1.4 定义私有的
      • 1.5 组件中的data方法
    • (2)Vue组件之间传值
      • 2.1 父组件向子组件传值
      • 2.2 子组件向父组件传值
      • 2.3 子组件调用父组件方法
      • 2.4 父组件调用子组件方法
      • 2.5 兄弟之间的传递
    • (3)组件插槽
      • 3.1 组件插槽的作用
      • 3.2 组件插槽的基本用法
      • 3.3 匿名插槽
      • 3.4 具名插槽
      • 3.5 作用域插槽

(四)生命周期

  • 什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!
  • 生命周期钩子:就是生命周期事件的别名而已;
  • 生命周期钩子 = 生命周期函数 = 生命周期事件
    06 day2-Vue.js 黑马全家桶笔记_第1张图片
    创建期间的生命周期函数:
    • beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
    • created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
    • beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
    • mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示

运行期间的生命周期函数:

  • beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
  • updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!

销毁期间的生命周期函数:

  • beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
  • destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
<script>
   // 创建 Vue 实例,得到 ViewModel
   var vm = new Vue({
     el: '#app',
     data: {
       msg: 'ok'
     },
     methods: {
       show() {
         console.log('执行了show方法')
       }
     },
     beforeCreate() { // 这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
       // console.log(this.msg)
       // this.show()
       // 注意: 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化
     },
     created() { // 这是遇到的第二个生命周期函数
       // console.log(this.msg)
       // this.show()
       //  在 created 中,data 和 methods 都已经被初始化好了!
       // 如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作
     },
     beforeMount() { // 这是遇到的第3个生命周期函数,表示 模板已经在内存中编辑完成了,但是尚未把 模板渲染到 页面中
       // console.log(document.getElementById('h3').innerText)
       // 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串
     },
     mounted() { // 这是遇到的第4个生命周期函数,表示,内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
       // console.log(document.getElementById('h3').innerText)
       // 注意: mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动
     },


     // 接下来的是运行中的两个事件
     beforeUpdate() { // 这时候,表示 我们的界面还没有被更新【数据被更新了吗?  数据肯定被更新了】
       /* console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
       console.log('data 中的 msg 数据是:' + this.msg) */
       // 得出结论: 当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面尚未和 最新的数据保持同步
     },
     updated() {
       console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
       console.log('data 中的 msg 数据是:' + this.msg)
       // updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
     }
   });
 </script>

(五)数组

(1)数组变异方法

  • 在 Vue 中,直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变
  • 变异数组方法即保持数组方法原有功能不变的前提下对其进行功能拓展
push() 往数组最后面添加一个元素,成功返回当前数组的长度
pop() 删除数组的最后一个元素,成功返回删除元素的值
shift() 删除数组的第一个元素,成功返回删除元素的值
unshift() 往数组最前面添加一个元素,成功返回当前数组的长度
splice() 有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除 后想要在原位置替换的值
sort() sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组
reverse() reverse() 将数组倒序,成功返回倒序后的数组

(2)替换数组

  • 不会改变原始数组,但总是返回一个新数组
filter filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
concat concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组
slice slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组

(3)动态数组响应式数据

  • Vue.set(a,b,c) 让 触发视图重新更新一遍,数据动态起来
  • a是要更改的数据 、 b是数据的第几项、 c是更改后的数据

(六)组件

(1)组件注册

1.1 使用 Vue.extend 配合 Vue.component 方法

<body>
  <div id="app">
    <!-- 如果要使用组件,直接,把组件的名称,以 HTML 标签的形式,引入到页面中,即可 -->
    <mycom1></mycom1>
  </div>
 
  <script>
    // 1.1 使用 Vue.extend 来创建全局的Vue组件
    // var com1 = Vue.extend({
    //   template: '

这是使用 Vue.extend 创建的组件

' // 通过 template 属性,指定了组件要展示的HTML结构
// }) // 1.2 使用 Vue.component('组件的名称', 创建出来的组件模板对象) // Vue.component('myCom1', com1) // 如果使用 Vue.component 定义全局组件的时候,组件名称使用了 驼峰命名,则在引用组件的时候,需要把 大写的驼峰改为小写的字母,同时,两个单词之前,使用 - 链接; // 如果不使用驼峰,则直接拿名称来使用即可; // Vue.component('mycom1', com1) // Vue.component 第一个参数:组件的名称,将来在引用组件的时候,就是一个 标签形式 来引入 它的 // 第二个参数: Vue.extend 创建的组件 ,其中 template 就是组件将来要展示的HTML内容 Vue.component('mycom1', Vue.extend({ template: '

这是使用 Vue.extend 创建的组件

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

1.2 直接使用 Vue.component 方法

  • 注意组件只能有一个根元素,可以用一个div括起来。
  • 注意驼峰写法(首字母大写),要变成xx-yyy
  • 如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件;但是在普通的标签模板中,必须使用短横线的方式使用组件
<body>
  <div id="app">
    <!-- 还是使用 标签形式,引入自己的组件 -->
    <mycom2></mycom2>
  </div>
 
  <script>
    // 注意:不论是哪种方式创建出来的组件,组件的 template 属性指向的模板内容,必须有且只能有唯一的一个根元素
    Vue.component('mycom2', {
      template: '

这是直接使用 Vue.component 创建出来的组件

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

1.3 定义在外面

  <div id="app2">
    <mycom3></mycom3>
    <login></login>
  </div>
 
  <!-- 在 被控制的 #app 外面,使用 template 元素,定义组件的HTML模板结构  -->
  <template id="tmpl">
    <div>
      <h1>这是通过 template 元素,在外部定义的组件结构,这个方式,有代码的只能提示和高亮</h1>
      <h4>好用,不错!</h4>
    </div>
  </template>
 
  <script>
    Vue.component('mycom3', {
      template: '#tmpl'
    })
 </script>

1.4 定义私有的

<body>
  <div id="app2">
    <login></login>
  </div>
  <template id="tmpl2">
    <h1>这是私有的 login 组件</h1>
  </template>
 
  <script>
    var vm2 = new Vue({
      el: '#app2',
      data: {},
      methods: {},
      filters: {},
      directives: {},
      components: { // 定义实例内部私有组件的
        login: {
          template: '#tmpl2'
        }
      }
    })
  </script>
</body>

1.5 组件中的data方法

 <script>
    // 1. 组件可以有自己的 data 数据
    // 2. 组件的 data 和 实例的 data 有点不一样,实例中的 data 可以为一个对象,但是 组件中的 data 必须是一个方法
    // 3. 组件中的 data 除了必须为一个方法之外,这个方法内部,还必须返回一个对象才行;
    // 4. 组件中 的data 数据,使用方式,和实例中的 data 使用方式完全一样!!!
    Vue.component('mycom1', {
      template: '

这是全局组件 --- {{msg}}

'
, data: function () { return { msg: '这是组件的中data定义的数据' } } }) // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {} }); </script>

(2)Vue组件之间传值

2.1 父组件向子组件传值

  • 1 组件内部通过props接收传递过来的值
Vue.component('menu-item', {  
      props: ['title'],
      template: '
{{title}}
' })
  • 2 父组件通过属性绑定将值传递给子组件
 
 
<body>
  <div id="app">
    <!-- 父组件,可以在引用子组件的时候, 通过 属性绑定(v-bind:) 的形式, 把需要传递给子组件的数据,以属性绑定的形式,传递到子组件内部,供子组件使用 -->
    <com1 v-bind:parentmsg="msg"></com1>
  </div>
  
  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        msg: '123 啊-父组件中的数据'
      },
      methods: {},
      components: {
        // 结论:经过演示,发现,子组件中,默认无法访问到 父组件中的 data 上的数据 和 methods 中的方法
        com1: {
          data() { // 注意: 子组件中的 data 数据,并不是通过 父组件传递过来的,而是子组件自身私有的,比如: 子组件通过 Ajax ,请求回来的数据,都可以放到 data 身上;
            // data 上的数据,都是可读可写的;
            return { }
          },
          props: ['parentmsg'], // 把父组件传递过来的 parentmsg 属性,先在 props 数组中,定义一下,这样,才能使用这个数据
          template: '

这是子组件 --- {{ parentmsg }}

'
, // 注意: 组件中的 所有 props 中的数据,都是通过 父组件传递给子组件的 // props 中的数据,都是只读的,无法重新赋值 methods: { change() { this.parentmsg = '被修改了' } } } } }); </script> </body>

2.2 子组件向父组件传值

  • 1 子组件通过自定义事件v-on(@),向父组件传递信息

  • 2 父组件监听子组件的事件
 

2.3 子组件调用父组件方法

1 与传值类似,子组件用$emit()触发自定义事件, $emit() 第一个参数为 自定义的事件名称,第二个参数为需要传递的数据
2.父组件中v-on监听该事件封装一个处理逻辑,然后父组件就可以使用了。

  • 1 子组件通过自定义事件v-on(@),向父组件传递信息

  • 2 父组件监听子组件的事件
 
<div id="app">
    <div :style='{fontSize: fontSize + "px"}'>{{pmsg}}</div>
     <!-- 2 父组件用v-on 监听子组件的事件
		这里 enlarge-text  是从 $emit 中的第一个参数对应   handle 为对应的事件处理函数	
	-->	
    <menu-item :parr='parr' @enlarge-text='handle($event)'></menu-item>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /* 子组件向父组件传值-携带参数 */
    Vue.component('menu-item', {
      props: ['parr'],
      template: `
        
  • {{item}}
### 1、子组件用$emit()触发事件 ### 第一个参数为 自定义的事件名称 第二个参数为需要传递的数据
`
}); var vm = new Vue({ el: '#app', data: { pmsg: '父组件中内容', parr: ['apple','orange','banana'], fontSize: 10 }, methods: { handle: function(val){ // 扩大字体大小 this.fontSize += val; } } }); </script>

2.4 父组件调用子组件方法

① 父组件中在引入的子组件中写入 ref = “mychild” mychid为自己定义的实例名
② 在函数中写 this.refs.mychild.testNum()。 “testNum”为子组件中定义的函数名
③子组件定义一个函数,让父组件调用即可,我定义的位testNum
④这个方法也可以进行传值,在括号中写入值,子组件接收即可 。
父组件:

<template>
  <div>
    <p class="father">父组件</p>
    <button @click="childClick">调用子组件方法</button>
    <child ref="mychild" ></child>
  </div>
</template>

<script>
import child from './child'
export default {
  components: {
    child
  },
  data() {
    return {
    }
  },
  methods: {
    childClick() {
      this.$refs.mychild.testNum(9809)
    }
  }
}
</script>

子组件:

<template>
  <div>
    <p class="child">子组件</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
    }
  },
  methods: {
    testNum(e) {
      console.log('调用了子组件中的方法 11111',e)
    }
  }
}
</script>

2.5 兄弟之间的传递

  • 1 兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据 ,提供事件中心 var hub = new Vue()
  • 2 监听与销毁事件
  hub.$on('add-todo', addTodo)
  hub.$off('add-todo')
  • 3 触发事件
    hub.$emit('add-todo', id)
  • 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)
  • 接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
  • 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
 <div id="app">
    <div>父组件</div>
    <div>
      <button @click='handle'>销毁事件</button>
    </div>
    <test-tom></test-tom>
    <test-jerry></test-jerry>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      兄弟组件之间数据传递
    */
    //1、 提供事件中心
    var hub = new Vue();

    Vue.component('test-tom', {
      data: function(){
        return {
          num: 0
        }
      },
      template: `
        
TOM:{{num}}
`
, methods: { handle: function(){ //2、传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据) 触发兄弟组件的事件 hub.$emit('jerry-event', 2); } }, mounted: function() { // 3、接收数据方,通过mounted(){} 钩子中 触发hub.$on(方法名 hub.$on('tom-event', (val) => { this.num += val; }); } }); Vue.component('test-jerry', { data: function(){ return { num: 0 } }, template: `
JERRY:{{num}}
`
, methods: { handle: function(){ //2、传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据) 触发兄弟组件的事件 hub.$emit('tom-event', 1); } }, mounted: function() { // 3、接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名 hub.$on('jerry-event', (val) => { this.num += val; }); } }); var vm = new Vue({ el: '#app', data: { }, methods: { handle: function(){ //4、销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据 hub.$off('tom-event'); hub.$off('jerry-event'); } } }); </script>

06 day2-Vue.js 黑马全家桶笔记_第2张图片

(3)组件插槽

组件的最大特性就是复用性,而用好插槽能大大提高组件的可复用能力

3.1 组件插槽的作用

父组件向子组件传递内容
06 day2-Vue.js 黑马全家桶笔记_第3张图片

3.2 组件插槽的基本用法

  • 1 插槽位置
Vue.component('alert-box', {
     template: `
       
ERROR:
` })
  • 2 插槽内容

lalalala

3.3 匿名插槽

<div id="app">
  <!-- 这里的所有组件标签中嵌套的内容会替换掉slot  如果不传值 则使用 slot 中的默认值  -->  
  <alert-box>有bug发生</alert-box>
  <alert-box>有一个警告</alert-box>
  <alert-box></alert-box>
</div>

<script type="text/javascript">
  /*
    组件插槽:父组件向子组件传递内容
  */
  Vue.component('alert-box', {
    template: `
      
ERROR: # 当组件渲染的时候,这个 元素将会被替换为“组件标签中嵌套的内容”。 # 插槽内可以包含任何模板代码,包括 HTML 默认内容
`
}); var vm = new Vue({ el: '#app', data: { } }); </script> </body> </html>

06 day2-Vue.js 黑马全家桶笔记_第4张图片

3.4 具名插槽

  • 具有名字的插槽
  • 使用 中的 “name” 属性绑定元素
    06 day2-Vue.js 黑马全家桶笔记_第5张图片

  <div id="app">
    <base-layout>
       <!-- 2、 通过slot属性来指定, 这个slot的值必须和下面slot组件得name值对应上
				如果没有匹配到 则放到匿名的插槽中   --> 
      <p slot='header'>标题信息</p>
      <p>主要内容1</p>
      <p>主要内容2</p>
      <p slot='footer'>底部信息信息</p>
    </base-layout>

    <base-layout>
      <!-- 注意点:template临时的包裹标签最终不会渲染到页面上     -->  
      <template slot='header'>
        <p>标题信息1</p>
        <p>标题信息2</p>
      </template>
      <p>主要内容1</p>
      <p>主要内容2</p>
      <template slot='footer'>
        <p>底部信息信息1</p>
        <p>底部信息信息2</p>
      </template>
    </base-layout>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      具名插槽
    */
    Vue.component('base-layout', {
      template: `
        
### 1、 使用 中的 "name" 属性绑定元素 指定当前插槽的名字
### 注意点: ### 具名插槽的渲染顺序,完全取决于模板,而不是取决于父组件中元素的顺序
`
}); var vm = new Vue({ el: '#app', data: { } }); </script> </body> </html>

06 day2-Vue.js 黑马全家桶笔记_第6张图片

3.5 作用域插槽

  • 父组件对子组件内容加工处理
  • 既可以复用子组件的slot,又可以使slot内容不一致
    06 day2-Vue.js 黑马全家桶笔记_第7张图片
<div id="app">
    <!-- 
		1、当我们希望li 的样式由外部使用组件的地方定义,因为可能有多种地方要使用该组件,
		但样式希望不一样 这个时候我们需要使用作用域插槽 
		
	-->  
    <fruit-list :list='list'>
       <!-- 2、 父组件中使用了<template>元素,而且包含scope="slotProps",
			slotProps在这里只是临时变量   
		---> 	
      <template slot-scope='slotProps'>
        <strong v-if='slotProps.info.id==3' class="current">
            {{slotProps.info.name}}		         
         </strong>
        <span v-else>{{slotProps.info.name}}</span>
      </template>
    </fruit-list>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      作用域插槽
    */
    Vue.component('fruit-list', {
      props: ['list'],
      template: `
        
  • ### 3、 在子组件模板中,元素上有一个类似props传递数据给组件的写法msg="xxx", ### 插槽可以提供一个默认内容,如果如果父组件没有为这个插槽提供了内容,会显示默认的内容。 如果父组件为这个插槽提供了内容,则默认的内容会被替换掉 {{item.name}}
  • `
    }); var vm = new Vue({ el: '#app', data: { list: [{ id: 1, name: 'apple' },{ id: 2, name: 'orange' },{ id: 3, name: 'banana' }] } }); </script> </body> </html>

    在这里插入图片描述

    你可能感兴趣的:(前端学习笔记-vue)