Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)

■ 目录

混入(mixins)好处

什么是组件,为什么要有组件&组件的好处(!!!)

组件语法,创建父子组件

组件传值/通信(!!!

组件通信的语法(!!!

生命周期&钩子函数概念&作用(!!!

一、混入(Mixin !)

明确需求

Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第1张图片

说明:后期是多个页面,每个页面都new Vue

因此:就会出现举例普通方法冗余 同一段代码写了多次

解决:通过混入(mixin)从而提高代码复用性,减少冗余

语法

###局部
const 变量 = {
	data() {// 1通过data来存放公共数据,2留心之前data是对象,现在data是函数返回对象
        return {
            // 模型数据
        }
	},
	methods:{}    //  留心:方法中使用模型数据,先用newVue模型中的,再用混入模型中的
	//...
}

// 大家熟悉的语法
new Vue({
	mixins: [变量名,...,变量名]  // 作用:将公共代码混入进来,留心:变量名不能加引号 加引号就是字符串
    el,
    data: {},
    methods,
    computed,
    watch
})


###全局(不需要去new Vue整合 直接所有都可以
Vue.mixin({
    data,
    methods
    ...
})

代码推进

步骤1:创建两个Vue对象分别监控app1和app2

步骤2:app1显示uname=小明1和age=1模型数据 & 点击方法弹出模型中的姓名

步骤3:app2显示uname=小明2和age=2模型数据 & 点击方法弹出模型中的姓名

代码:

DOCTYPE html>
<html lang="en">
<head>
<title>vuetitle>
<meta charset="UTF-8">
head>
<body>
<div id="app1">
    <button @click="fn">点击弹框button>
div>

<div id="app2">
    <button @click="fn">点击弹框button>
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
// 步骤1:创建两个Vue对象分别监控app1和app2
// 步骤2:app1显示uname=小明1和age=1模型数据 & 点击方法弹出模型中的姓名
// 步骤3:app2显示uname=小明2和age=2模型数据 & 点击方法弹出模型中的姓名

const vm1 = new Vue({
    el: '#app1',
    data: {
        uname: "小明1",
        age: 1
    },
    methods: {
        fn() {
            alert(this.uname)
        }
    }
})

const vm2 = new Vue({
    el: '#app2',
    data: {
        uname: "小明2",
        age: 2
    },
    methods: {
        fn() {
            alert(this.uname)
        }
    }
})
script>
body>
html>

发现:模型中的数据uname是不同的,但是methods中的方法代码一样,冗余

解决:通过mixin混入技术

代码1:

<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app1">
    <button @click="fn">点击弹框</button>
</div>

<div id="app2">
    <button @click="fn">点击弹框</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 步骤1:创建两个Vue对象分别监控app1和app2
// 步骤2:app1显示uname=小明1和age=1模型数据 & 点击方法弹出模型中的姓名
// 步骤3:app2显示uname=小明2和age=2模型数据 & 点击方法弹出模型中的姓名

const mixinOne = {
    // data() { return {} }
    // methods: {}
    // computed: {}
    data() {
        return {
            uname: "张三"
        }
    },
    methods: {
        fn() {
            alert(this.uname)  // 先有自己的,自己的没有再用公共的
        }  
    }
}

const vm1 = new Vue({
    // 融合公共代码,减少代码冗余   留心切记别加引号
    mixins: [mixinOne], 
    el: '#app1',
    data: {
        // uname: "小明1",
        age: 1
    },
})

const vm2 = new Vue({
    // 融合公共代码,减少代码冗余
    mixins: [mixinOne],
    el: '#app2',
    data: {
        uname: "小明2",
        age: 2
    },
})
</script>
</body>
</html>

代码2:

<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app1">
    <button @click="fn">点击弹框</button>
</div>

<div id="app2">
    <button @click="fn">点击弹框</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 步骤1:创建两个Vue对象分别监控app1和app2
// 步骤2:app1显示uname=小明1和age=1模型数据 & 点击方法弹出模型中的姓名
// 步骤3:app2显示uname=小明2和age=2模型数据 & 点击方法弹出模型中的姓名

Vue.mixin({
    methods: {
        fn() {
            alert(this.uname)
        }
    }
})

const vm1 = new Vue({
    el: '#app1',
    data: {
        uname: "小明1",
        age: 1
    },
})

const vm2 = new Vue({
    el: '#app2',
    data: {
        uname: "小明2",
        age: 2
    },
})
</script>
</body>
</html>

二、组件(Component)

需求

Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第2张图片

组件(Component)是vue最强大的功能之一

将一个大型网站划分成一个个更小的可控单元(一个个组件 里面放html、css、js)

什么是组件?

就是一个文件(其实就是以前的html只不过语法不同了)里面存放html、js、css

这样有什么好处?

减少代码冗余,方便后期维护,因为它提出了一个概念,封装公共代码相互引用

语法

说明:组件很重要,但写项目语法会比这个简单很多 因为框架封装了

定义

###局部的 也就是说你要在new Vue中写
const vm = new Vue({
    el:
    //...
    components: {
        标签名: {
            template: `写HTML代码`,
            data() {return {}},
            methods
            //...
        }
    }
})

###全局的
Vue.component(标签名, {
    template: `放HTML代码`,  // template 模板 也就是html
    data() {return {}},
    methods: {}
    //...
})

调用

在【监控范围】内,直接写<标签名>

留心:如果标签名大写,需要将大写改成-小写(因为HTML不识别大小写

组件的创建

  • 需求
自定义组件mytag1输出:

我叫MT1:T1

自定义组件mytag2输出:

我叫MT2:T2

  • 代码
DOCTYPE html>
<html lang="en">
<head>
<title>vuetitle>
<meta charset="UTF-8">
head>
<body>
<div id="app">
    <mytag1>mytag1>
    <mytag2>mytag2>
    
    <my-tag3>my-tag3>
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
// 自定义组件mytag1输出:

我叫MT1:T1

// 自定义组件mytag2输出:

我叫MT2:T2

Vue.component('mytag1', { template: `

我叫MT1:T1

`
}) Vue.component('mytag2', { template: `

我叫MT2:T2

`
//ES6模板字符串语法 }) Vue.component('myTag3', { template: `

webopen

`
}) const vm = new Vue({ el: '#app', data: { } })
script> body> html>

组件中使用指令(渲染数据&事件)

  • 需求
自定义组件mytag1输出:

你好,MT,听说你年薪1w

变量:name-MT,money-1 事件:p-click弹出hello,word
  • 代码
DOCTYPE html>
<html lang="en">
<head>
<title>vuetitle>
<meta charset="UTF-8">
head>
<body>
<div id="app">
    
    <mytag1 />
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
// 自定义组件mytag1输出:

你好,MT,听说你年薪1w

// 变量:name-MT,money-1 // 事件:p-click弹出hello,word Vue.component('mytag1', { // 组件名随意但是留意大小写 template: `

你好,{{name}},听说你年薪{{money}}w

`
, data(){ return { name: 'MT', money: 1 } }, methods: { say() { alert('hello,word') } } }) const vm = new Vue({ el: '#app', data: { } })
script> body> html>
  • 总结
如何在组件中显示数据: 通过模板语法{{data中的键}}
如何在组件中使用事件: 通过事件语法@事件类型="函数名"

父子组件的创建

  • 需求
自定义组件mytag1输出:

你好,MT(退出),听说你很M

变量:name-MT,age-100 事件:p-click弹出hello 注意:退出位置用a标签创建子组件
  • 代码
DOCTYPE html>
<html lang="en">
<head>
<title>vuetitle>
<meta charset="UTF-8">
head>
<body>
<div id="app">
    <mytag1 />
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
// 自定义组件mytag1输出:

你好,MT(退出),听说你很M

// 变量:name-MT,age-100 // 事件:p-click弹出hello // 注意:退出位置用a标签创建子组件 Vue.component('mytag1', { template: `

你好,{{name}}(),听说你很M,{{age}}岁了

`
, data() { return { name: "MT", age: 100 } }, methods: { say() { alert('hello') alert(this.age) } }, // 通过components来声明子组件 调用同之前的 components: { // 键就是标签名 值是对象 内容一样 logout: { template: `退出` } } }) const vm = new Vue({ el: '#app', data: { } })
script> body> html>

三、动态组件(了解)

- 利用component标签和is属性实现

效果图

Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第3张图片

语法

步骤1:定义组件/页面,语法创建(注:也有简化语法

步骤2:在页面调用显示即可

代码

  1. 造导航 ul>li*4
  2. 造组件 4
  3. 显示组件
  4. 动态显示组件(点击导航切换
DOCTYPE html>
<html lang="en">
<head>
<title>vuetitle>
<meta charset="UTF-8">
head>
<body>
<div id="app">
    <ul>
        <li @click="chooseCompontent = 'index'">首页li>
        <li @click="chooseCompontent = 'jiadian'">家电li>
        <li @click="chooseCompontent = 'baojian'">保健li>
        <li @click="chooseCompontent = 'meirong'">美容li>
    ul>
    
     <component v-bind:is="chooseCompontent">component>
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
// 造组件
Vue.component('index', {
    template: `
这是首页页面
`
}) Vue.component('jiadian', { template: `
这是家电页面
`
}) Vue.component('baojian', { template: `
这是保健页面
`
}) Vue.component('meirong', { template: `
这是美容页面
`
}) const vm = new Vue({ el: '#app', data: { chooseCompontent: 'jiadian' } })
script> body> html>

四、组件通信/传值(!!!)

需求

Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第4张图片
加入商品组件里面触发点击事件,需要更改头部组件里面的数据

如何实现?

通过组件通信技术

语法

父组件->子组件:通过props接受父传递数据

步骤1:子通过props键来接受父传递的数据  props:['变量名',...,'变量名']  
								   #注:这么写就相当于在子组件data中声明数据了
步骤2:父传递给子   父在调用子的组件上通过语法 v-bind:子组件props中的变量名="父组件中的data数据"

子组件->父组件:通过$emit创建自定义事件发送数据

步骤1:子创建自定义事件    	 通过语法  this.$emit(事件名称,数据1,...,数据n)
步骤2:父调用自定义事件获取数据  父必须在调用的子组件上触发事件,语法@自定义事件="函数名"

留心1:函数在父定义
留心2:底层会将自定义事件中的数据 传递给函数的形参

兄弟组件:通过EventBus(事件总线)

const eventBus = new Vue()   // 相当于创建一个组件数据共享中心

// 发送数据:eventBus.$emit(自定义事件名称,数据1,.....,数据n)
// 接受数据(监控传递):eventBus.$on(自定义事件名称,处理函数)

组件通信(父-子)

  • 需求
自定义组件fathertag输出:

我是父组件,我儿子叫:赵冠希

我是子组件,我爸爸给我取名:赵冠希

其中子组件sontag部分:【】 变量:sonName-赵冠希 为了更明显看出父子关系推荐:https://www.w3school.com.cn/tags/tag_fieldset.asp
  • 代码
    Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第5张图片
DOCTYPE html>
<html lang="en">
<head>
<title>vuetitle>
<meta charset="UTF-8">
head>
<body>
<div id="app">
    <fathertag>fathertag>
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
Vue.component("fathertag", {
    
    // 声明父组件中的数据
    data() {
        return {
            sonName: '赵冠希' // 调用的时候注意大小写
        } 
    },
    // 声音父组件内容
    template: `
        
父组件

我是父组件,我儿子叫:{{sonName}}

`
, // 声明普通方法 methods: {}, // 声明子组件 components: { // 键 - 子组件标签名,值 - 是对象里面有template、data、methods等 sontag: { // 声明props属性来接受父传递的数据 props: ["myName"], // 留心:这么写就相当于在子的data中声明了myName模型数据 // 声明子组件的内容 template: `
子组件

我是子组件,我爸爸给我取名:{{myName}}

`
} } }) const vm = new Vue({ el: '#app', data: { } })
script> body> html>

组件通信(子-父)

  • 需求
上述代码基础上,在父组件fn1方法中能够获取子的myName2数据

子创建getSonData事件
父通过showSonData方法获取
  • 代码
    Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第6张图片
<!DOCTYPE html>
<html lang="en">
<head>
<title>vue</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
    <fathertag></fathertag>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('fathertag', {
    // 声明父组件的内容
    template: `
        
父组件

我是父组件,我儿子叫:{{mySonData}}

`
, // 声明父的模型数据 data() { return { mySonData: '' } }, // 声明父的普通方法 methods: { showSonDataFn(data) { // 这边有形参,几个呢 看自定义事件中传递了几个 // console.log(data) this.mySonData = data } }, // 声明子组件 components: { // 键-子组件名称,值-对象 里面有template、methods、data等 sontag: { // 声明子组件的内容 template: `
子组件

我是子组件,我爸爸给我取名:{{myName2}}

`
, // 声明子组件模型数据 data() { return { myName2: '小明' } }, // 需求:子的数据传递给父用,因为父不能直接获取 // 思考:子声明时候创建自定义事件 // 回答:1 用户和网页交互后创建, 2 网页加载完毕后创建自定义事件 (目前的方案) // 之前:js中window.onload jq $(function() {}) // 现在:使用mounted() mounted() { // 目前简单理解为 // 网页加载完毕后创建自定义事件 // 创建自定义事件语法:this.$emit('事件名称', 数据1,...,数据n) // this.$emit("getSonData", 1111, 2222) this.$emit("getSonData", this.myName2) } } } }) const vm = new Vue({ el: '#app', data: { } }) </script> </body> </html>

组件通信(兄弟)

  • 需求
步骤1:分别定义mytag1和mytag2组件,先写fieldset然后写button
步骤2:点击mytag1组件中的按钮,将mytag1组件中的msg变量传递给mytag2使用
  • 代码 Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第7张图片
DOCTYPE html>
<html lang="en">
<head>
<title>vuetitle>
<meta charset="UTF-8">
head>
<body>
<div id="app">
    <mytag1>mytag1>
    <mytag2>mytag2>
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
// 定义数据共享中心
const eventBus = new Vue() 

Vue.component('mytag1', {
    data() {
        return {
            msg: 'data中的数据'
        }
    },
    template: `
        
兄弟1
`
, methods: { sendDataFn() { // 发送数据:eventBus.$emit('事件名称', 数据1,...,数据n) eventBus.$emit('mytag1MsgData', this.msg) } } }) Vue.component('mytag2', { template: `
兄弟2 这是我兄弟1传递的数据:【{{broData}}】
`
, data() { return { broData: '' } }, // 之前:js window.onload jq $(function(){}) // 现在:vue中 mounted() { // 接受数据(监控传递数据):eventBus.$on('事件名称', 处理函数) eventBus.$on('mytag1MsgData', (msg) => { // console.log(msg) this.broData = msg }) } }) const vm = new Vue({ el: '#app', data: { } })
script> body> html>

总结

首先:发现还是挺麻烦的,那别管那么多只要把握下述语法理解怎么用 然后复制实现即可

其次:主要搞明白父子、子父工作场景还是较为多,因为后面会有一个vuex库来代替

原理:上述语法是我总结的,官方参考手册

https://cn.vuejs.org/v2/guide/components-props.html
https://cn.vuejs.org/v2/guide/components-custom-events.html

父->子(!

步骤1:子通过props接受数据
步骤2:父在调用子组件的标签上通过v-bind传递数据即可

子->父(!

步骤1:子创建自定义事件,通过this.$emit语法
步骤2:父在调用子组件的标签上通过@自定义事件名称="函数名"获取数据

兄弟(!

步骤1:创建数据共享中心 const eventBus = new Vue()
步骤2:通过eventBus.$emit发送数据
步骤3:通过eventBus.$on监控接受数据

五、生命周期&钩子函数(!!!)

需求

Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第8张图片

说明:前面做过一个todolist案例数据是固定不变的

需求:数据动态,也就是请求接口。

思考:什么时候发送异步请求? 换句话说在哪写代码(以前:onload和$(function(){})

现在: mounted

语法说明

生命周期:指代码可用和不可用时间(举例:局部变量声明周期,函数调用产生,函数调动完毕销毁)
钩子函数:在指定场景下触发的普通函数

https://cn.vuejs.org/v2/guide/instance.html#生命周期图示

Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第9张图片

代码推进

  • 代码
    Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第10张图片
    Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第11张图片
    Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第12张图片
DOCTYPE html>
<html lang="en">
<head>
<title>vuetitle>
<meta charset="UTF-8">
head>
<body>
<div id="app">
    {{msg}}
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
const vm = new Vue({
    el: '#app',
    data: {
        msg: "神龙之母"
    },
    beforeCreate() {
        console.group("beforeCreate:HTML没有剪切,模型没有初始化")
        console.log(this.$el)   // 打印剪切到内存中的数据
        console.log(this.$data) // 打印已经初始化后的模型数据
        console.log(this.msg)   // 打印模型中的数据
        console.groupEnd()
    },
    created() {
        console.group("created:HTML没有剪切,模型已经初始化")
        console.log(this.$el)   // 打印剪切到内存中的数据
        console.log(this.$data) // 打印已经初始化后的模型数据
        console.log(this.msg)   // 打印模型中的数据
        console.groupEnd()
    },
    beforeMount() {
        console.group("beforeMount:HTML已经剪切,HTML数据还没替换,模型已经初始化")
        console.log(this.$el)   // 打印剪切到内存中的数据
        console.log(this.$data) // 打印已经初始化后的模型数据
        console.log(this.msg)   // 打印模型中的数据
        console.groupEnd()
    },
    mounted() { // 挂载完毕,监控范围里面有vue语法 已经全部替换成最终数据
        console.group("mounted:模型已经初始化、HTML数据已经替换完毕,并且放到了监控范围中")
        console.log(this.$el)   // 打印剪切到内存中的数据
        console.log(this.$data) // 打印已经初始化后的模型数据
        console.log(this.msg)   // 打印模型中的数据
        console.groupEnd()
    },

    
    beforeUpdate() {
        console.group("beforeUpdate")
        console.log('模型数据修改前触发') 
        console.groupEnd()
    },
    updated() {
        console.group("updated")
        console.log('模型数据修改后触发') 
        console.groupEnd()
    },
    beforeDestroy() {
        console.group("beforeDestroy:组件销毁前")
        console.groupEnd()
    },
    destroyed() {
        console.group("destroyed:组件销毁后")
        console.groupEnd()
    }

})
script>
body>
html>
  • 在beforeCreate和mounted中谁能够输出模型中值?为什么?
mounted

beforeCreate  监控范围中的HTML未剪切到内存、模型未初始化
mounted  HTML已剪切到内存、HTML挂载/监控范围里面的vue模板语法替换成最终的数据 放到页面中、模型已初始化
		 脚下留心:mounted目前说已经挂载了(但:有特殊情况 它并不能保证 后面说 nextTick

Vue基础(混入mixin、组件component、动态组件、组件通信传值/父子通信等、生命周期)_第13张图片

你可能感兴趣的:(Vue—生命周期,Vue,vue)