vue学习---基于vue2中的组件、组件通信、ref

vue学习—基于vue2中的组件

此篇是基于 vue2.x 的开发环境

1.组件

1.1注册组件

在项目文件夹下的src文件夹下的components文件夹下创建的一个.vue文件就是一个组件,组件的script中使用this,这个this代表当前组件的实例

局部注册

先通过import 组件名 from ‘组件路径’ 导入组件;在export default 中用components注册组件

示例代码:

写在App.vue文件中







全局注册

依旧是先导入组件,再注册组件通过vue.component(’ 组件名 ’ , 导入组件名)

示例代码:

在main.js文件中

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// 导入Search组件
import Search from './components/Search.vue'
// 注册组件(全局组件,可以在所有的.vue文件中使用)
Vue.component('Search', Search);

//实例化Vue对象
new Vue({
  render: h => h(App),
}).$mount('#app')

组件的使用

使用组件(可以是全局组件 或 局部组件)

在在App.vue文件中使用:<组件名/> 或者 <组件名><组件名/>

1.2关于模块(一个模块就是一个js文件)的导入、导出

在项目文件夹下的src文件夹下创建一个文件utils放置创建的js文件

第一种:默认导出

导出:export default 要导出的变量名

导入:import 导出的变量名 from ‘路径’

示例代码:

新建的js文件导出:

//定义函数
function add(a,b){
    return a+b;
}

//默认抛出(导出)
export default add;

main.js文件导入:

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false
// 默认导入 可以给默认导入的数据改名
// 默认导出和默认导入 配合使用
import abc from './utils/a'
console.log( abc(10,20) );

//实例化Vue对象
new Vue({
  render: h => h(App),
}).$mount('#app')

第二种:命名导出

导出:export { 变量名1,变量名2 ,…}

导入:import {变量名1,变量名2,…} from ‘路径’

示例代码:

js文件导出:

function sub(a,b){
    return a-b;
}
function mul(a,b){
    return a*b;
}

//命名导出
export {
    sub,
    mul
};

main.js文件导入

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// 命名导入
// 命名导入导出是对应的配合使用的,命名变量名字要相同

// {sub,mul}解构赋值,解析出你想要导入的文件
// 命名导入,必须以{}的形式导入解构时不能改名字要和导出中的名字一样
import {sub,mul} from './utils/b';

console.log(sub(10,20),mul(10,20));

console.log(abc(10,20));

//实例化Vue对象
new Vue({
  render: h => h(App),
}).$mount('#app')

1.3组件生命周期钩子

生命周期钩子是在Vue组件实例生命周期的某个阶段执行的已定义方法。从初始化开始到它被销毁,实例对象都会遵循不同的生命阶段。这是一个着名的图表,表示钩子函数执行顺序。

vue学习---基于vue2中的组件、组件通信、ref_第1张图片
vue学习---基于vue2中的组件、组件通信、ref_第2张图片

  • beforeCreate:在实例初始化之后创建完成之前,数据观测(data observer)和 event/watcher事件配置之前被调用
  • created:在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, event/watch事件回调。然而,挂载阶段还没有开始,$el属性目前不可见。
  • beforeMount:挂载开始之前被调用:相关的render函数首次被调用。
  • mounted:el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。如果root实例挂载了一个文档内元素,当mounted被调用时vm.$el也在文档内。
  • beforeUpdate:数据更新时调用,发生在虚拟DOM打补丁之前。这里适合在更新之前访问现有的DOM,比如手动移出已添加的事件监听器。
  • updated:由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。
  • beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
  • destroyed:Vue实例销毁后调用哪个。调用后,vue实例指示的所有东西都会解绑定,所有的事件监听器会被移出,所有的子实例也会被销毁。

注意:

  1. 以上这些函数都是组件的什么周期函数,它们在组件生命过程中会在特定时刻自动调用。
  2. 实例化期里的方法只会执行以此份
  3. 挂载期里的方法只会执行一次;对于哪些组件挂载完成前必须执行而且只能执行一次的代码可以写在 mounted 函数中,在这里可以发送ajax请求,创建定时器,事件监听
  4. 更新期里的两个方法会随着组件更新反复执行
  5. 销毁期只会执行一次;如果 mounted 生命周期函数中做了发送ajax请求,创建定时器,事件监听(滚动条事假,键盘事件,绑定点击事件)等操作,这些操作会占用计算机内存,在组件销毁前如果没有及时释放这些内存,就会导致内存泄漏。
  6. $destroy():销毁组件的方法,组件销毁不一定是组件消失只是组件不能用了。

示例代码:

App.vue文件







2.组件通信

所谓组件通信,即组件和组件之间的数据传递,包含两个方面:

Ø 具有嵌套关系的父子组件之间数据的传递问题;

Ø 兄弟组件之间数据的传递问题;

具体可以分为:

  • 父组件向子组件传值
  • 子组件向父组件传值
  • 跨级组件传值
  • 兄弟组件之间传值

2.1父组件向子组件传值

当数据存在父组件中,需要将父组件中的数据传到子组件中

父组件在子组件身上通过自定义属性传值,子组件内部通过props接收值

父组件:

<div id="app">
    <div class="tabs">
      <!-- App.vue与渲染的组件之间是父子关系 -->
      <!-- 所有数据都存在于父组件中,需要将父组件中的数据传到子组件中进行渲染 -->

      <!-- 父组件向子组件传值:父组件在子组件身上通过自定义属性传值,子组件内部通过props接收值 -->
      <!-- 子组件向父组件传值:父组件提前在子组件身上绑定自定义事件,子组件内部通过$emit触发 -->

      <!-- 渲染左侧分类 -->
      <TabLeft :tabs="tabs" ></TabLeft>

      <!-- 渲染右侧分类 -->
      <TabRight ></TabRight>
    </div>
  </div>


export default {
    data() {
        return {
            // 用来保存当前点击的分类下标
            currentIndex: 0,
            tabs: [
                {
                    tabName: "三文鱼",
                    list: [
                        { pic: pic1, name: "三文鱼", price: 45 },
                        { pic: pic1, name: "高级三文鱼", price: 55 },
                        { pic: pic1, name: "vip三文鱼", price: 65 },
                    ]
                },
                {
                    tabName: "刺身",
                    list: [
                        { pic: pic2, name: "刺身", price: 45 },
                        { pic: pic2, name: "高级刺身", price: 55 },
                        { pic: pic2, name: "vip刺身", price: 65 },
                    ]
                },
                {
                    tabName: "大虾",
                    list: [
                        { pic: pic3, name: "大虾", price: 45 },
                        { pic: pic3, name: "高级大虾", price: 55 },
                        { pic: pic3, name: "vip大虾", price: 65 },
                    ]
                },
            ]
        };
    },
    components: { 
      TabRight,
      TabLeft,
     }

子组件:

export default {
    // 通过props接收从父组件传来的值,该值是只读的(不能修改)
    // props:['tabs','currentIndex']//数组形式
    props:{//对象形式,可以对传来的数据进行类型验证
        tabs:{type:Array, default:[]},
    }
}

2.2子组件向父组件传值

父组件提前在子组件身上绑定自定义事件,子组件内部通过$emit触发

on订阅,emit发布,on和emit是在Vue的原型上的,每个实例都可以调用。

父组件:

export default { data() { return { // 用来保存当前点击的分类下标 currentIndex: 0, tabs: [ { tabName: "三文鱼", list: [ { pic: pic1, name: "三文鱼", price: 45 }, { pic: pic1, name: "高级三文鱼", price: 55 }, { pic: pic1, name: "vip三文鱼", price: 65 }, ] }, { tabName: "刺身", list: [ { pic: pic2, name: "刺身", price: 45 }, { pic: pic2, name: "高级刺身", price: 55 }, { pic: pic2, name: "vip刺身", price: 65 }, ] }, { tabName: "大虾", list: [ { pic: pic3, name: "大虾", price: 45 }, { pic: pic3, name: "高级大虾", price: 55 }, { pic: pic3, name: "vip大虾", price: 65 }, ] }, ] }; }, components: { TabRight, TabLeft, }, methods:{ changelist(index){ this.currentIndex = index; } }

子组件:

 <div class="tab" :class="{active:currentIndex ==index}" @click="$emit('deliverIndex',index)" v-for="(item,index) in tabs" :key="index">{{item.tabName}}</div>
<div class="tabright">
    <!-- 渲染多个商品(列表) -->
    <div class="good" v-for="(item,index) in tabs[currentIndex].list" :key="index">
        <div class="imgbox">
            <img :src="item.pic" alt="">
        </div>
        <div class="text">
        <div class="name">{{item.name}}</div>
        <div class="price">{{item.price}}</div>
    </div>
    </div>
  </div>

**注意:**emit中传入的事件名称必须全部小写

2.3兄弟组件之间的通信

需要借助一个公共的eventbus (通信管道) 其中一个组件提前绑定事件,另外一个兄弟组件去触发事件并传值

创建一个空实例,例如:vm = new Vue({});作为通信桥梁;

在需要接收数据的组件中用vm.$on()监听自定义事件(一般在mounted函数中处理),并在回调函数中处理传递过来的参数(注意回调函数中的this处理);

在需要传值的组件中用vm.$emit()触发自定义事件,并传递数据;

实例化Vue空实例:

var vm = new Vue({});

步骤:

1.先在src中创建一个utils文件夹在该文件夹中创建一个tools.js文件,在该文件中实例化Vue空实例,并导出

import Vue from 'vue'

// 实例化Vue 并导出
export default new Vue()

2.在需要接收数据的组件中用vm.$on()监听自定义事件(一般在mounted函数中处理)

{{item.name}}
¥{{item.price}}
import eventbus from '../utils/tools' export default { // 通过props接收从父组件传来的值,该值是只读的(不能修改) data(){ return { currentIndex:0 } }, props:['tabs'], mounted(){ // 绑定事件 eventbus.$on('deliverIndex',(index=>{ this.currentIndex = index; //保存接收到的值 })) } }

3.在需要传值的组件中用vm.$emit()触发自定义事件,并传递数据;

触发事件并不一定要传值有可能只是触发这个事件

兄弟组件a:

{{item.tabName}}
// 导入空实例 import eventbus from '../utils/tools' export default { // 通过props接收从父组件传来的值,该值是只读的(不能修改) // props:['tabs','currentIndex'] //数组形式 data(){ return { currentIndex:0 } }, props:{//对象形式,可以对传来的数据进行类型验证 tabs:{type:Array,default:[]} }, methods:{ handleClick(index){ eventbus.$emit('deliverIndex',index);//触发事件并传值 this.currentIndex = index; } } }

2.4跨组件传值

外层组件通过provide传值, 内层组件通过inject接收值。

示例:

将外层组件中的值传给Child1组件再将值通过Child1组件传给Child2组件中再将值通过Child2组件传给Child3组件中

示例代码:

App.vue文件







Child1.vue文件






Child2.vue文件


  
  
  
  

Child3.vue文件


  
  
  
  

3.ref

获取dom节点:

通过ref属性给标签设置标识(别名),在js代码中通过this.$refs.xx 获取标识对应的dom节点

ref应用在组件身上

在js代码中通过this.$refs.xx获取标识对应的组件实例

示例代码:







关于ref的示例

购物车组件






父组件








@click.事件修饰符

@click.left:只有点击鼠标左键时候才会触发

@click.right:只有点击右键才会触发

@click.middle:必须点击鼠标滚轮才会触发点击事件

@click.prevent:阻止默认行为,例如:a标签的跳转

@click.ctrl:点击事件想要触发必须按Ctrl键

@click.shift:当按下shift键时才会触发

@click.native:把点击事件绑到子组件上时原生点击事件

自定义事件:子组件在父组件中使用时,直接绑定在子组件上的事件就是自定义事件,必须经过子组件的触发vm.$emit()才能执行 原生事件:直接在子组件里的模板上绑定的事件,子组件引入后是可以直接触发的

你可能感兴趣的:(#,vue学习笔记,vue.js,学习,javascript)