Vue2笔记--组件化基础

2022-12-31 14:28:25

Vue脚手架

1.Vue脚手架基础

官方提供的 Vue 官方 标准开发工具

官方文档:https://cli.vuejs.org/zh/

Vue CLI(command line interface)脚手架

0.配置淘宝镜像 不然会很慢 甚至安装失败

npm config set registry https://registry.npm.taobao.org

1.全局安装@vue/cli

npm install -g @vue/cli

2.切换到对应目录 创建脚手架

vue create vue_projectone

输入后会选择 使用Vue的版本 2/3/自定义

bable : ES6 语法转换为 ES5

eslint : 语法检查工具 检查代码是否合理

选择好之后输入回车

进行如下操作

  • cd 项目名
  • npm run serve

之后后开始编译代码

停止终端运行 ctrl + c 连续按两次 y/n 输入什么都会关闭

脚手架结构讲解

src

  • main.js 整个项目的入口文件
  • App.vue
  • .gitignore git 忽略上传git文件的 配置
  • babel.config.js babel的配置文件
  • package.json npm包配置文件
    • serve 代码执行后直接运行 man.js
    • build 构建 css js html
    • lint 进行语法检查
  • package-lock.json 包版本控制文件
  • README.md 教程

app.vue
image.png

app.vue内容**

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
    // 导入vue
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
} 
</script>

<style>
   /*写样式*/
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

public => index.html

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <!-- 针对IE浏览器的一个特殊配置,含义是让IE浏览器以最高的渲染级别渲染页面 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- 开启移动端的理想视口 -->
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <!-- 引入 favicon.ico  <%= BASE_URL %> 代表“./”底层有处理--> 
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <!--会将 package.json 中的内容当作标题 webpack相关内容 --> 
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
      <!--当浏览器不支持js时 noscript会渲染noscript的标签--> 
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
        <!--容器--> 
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

分析render函数

引入的是残缺的Vue 不含模板解析器

需要自己使用render #省体积 省空间

或者自己引入完整版vue

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

Vue.config.productionTip = false

new Vue({
    // h 官方说法是 createElement 是一个函数
    // createElement("h1","你好啊") 生成<h1>你好啊</h1>
    // 传入 组件 为渲染组件
  render: h => h(App),
}).$mount('#app')
/*
关于不同版本的Vue:
	1.vue.js 与vue.runtime.xxx.js的区别:
		(1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
		(2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
	2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement的数去指定具体内容。
*/

2.脚手架配置

Vue脚手架隐藏了所有webpack相关的配置,若想查看具体的webpakc配置,请执

vue inspect > output.js

// 仅仅是输出让你看的文件 在这里更改是无效的

如何自行配置?

配置参考 | Vue CLI (vuejs.org)

在 package.json 同级目录下创建 vue.config.js

// Commonjs 的暴露
// node.js 使用的 commonjs的暴露 不能用ES6
module.exports = {
  pages: {
    index: {
      // page 的入口
      entry: 'src/index/main.js',
      // 模板来源
      template: 'public/index.html',
      // 在 dist/index.html 的输出
      filename: 'index.html',
      // 当使用 title 选项时,
      // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
      title: 'Index Page',
      // 在这个页面中包含的块,默认情况下会包含
      // 提取出来的通用 chunk 和 vendor chunk。
      chunks: ['chunk-vendors', 'chunk-common', 'index']
    },
    // 当使用只有入口的字符串格式时,
    // 模板会被推导为 `public/subpage.html`
    // 并且如果找不到的话,就回退到 `public/index.html`。
    // 输出文件名会被推导为 `subpage.html`。
    subpage: 'src/subpage/main.js'
  }
}

关闭语法检查

lintOnSave:false //与page平级

3.ref属性

<h1 ref="title">H1标签</h1>
<School ref="sc">H1标签</School> 组件标签使用
<script>
    // vuecomponent 对象属性
    console.log(this.$refs.title) // 获取真实dom
    // 可在此处操作DOM
     console.log(this.$refs.sc) // 获得vc对象
</script>
<!-- 

1.被用来给元素或子组件注册引用信息(id的替代者)
2.应用在htm1标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
3.使用方式:
	打标识:<h1 ref="xxx ">.....</h1>或<School ref="xxx"></School>
	获取: this.$refs.xxx
-->

4.props配置

<template>
	<div>
        <!-- 传入data参数 -->
        <Student name="李四" sex="女" age="18"/>
    </div>
</template>

<template>
	<div>
        <!-- age不绑定为字符串 无法使用数字计算
			可以使用绑定 -->
        <Student name="李四" sex="女" :age="18"/>
    </div>
</template>

export default {
    // 加入此项配置项 接收数据
    props:['name','age','sex'],
    // 第二种写法 限制类型
    props:{
        name:String,
        age:Number,
        sex:String,
	}
    // 第三种写法
    props:{
    	name:{
    		type:String, // 指定类型
    		required:true, // 是否为必须的参数
    		default:"王二", // 不传参默认为该值
		}
	}
}

// props 中接收的数据无法更改 会报错
// 强行更改方法

new Vue({
    props:['name','age','sex'],
    data(){
        return {
            myAge = this.age;
        }
    }
    // 修改 myAge 代替 age
    // props 优先级更高 会优先展示
})
// props 不能传入 vue 已经使用的属性
// ref key ...
## 配置项props
功能:让组件接收外部传过来的数据
	(1).传递数据:
		<Demo name="xxx"/>
	(2).接收数据:
		第一种方式(只接收)∶
			props:["name"]
		第二种方式(限制类型):
			props:{
				name: Number
			}
		第三种方式(限制类型、限制必要性、指定默认值):
			    props:{
    	name:{
    		type:String, // 指定类型
    		required:true, // 是否为必须的参数
    		default:"王二", // 不传参默认为该值
		}
	}

备注: props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,
若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。

5.mixin(混入)

mixin.js

//两个组件共同使用相同的配置
export const mixin = {
    methods:{
        alert(this.name);
	}
}

export const mixin = {
    data(){
        return {
            x:200,
            y:200,
        }
    }
}

vue中的script

// 引入一个混合组件
import {mixin} from "../mixin";
export default {
    name:"School",
    // 复用配置
     mixins:[minxin,mixin2],
    // 数据重复
    // 不破坏原有数据 将现有数据与原有数据整合 如果重复现有数据优先级更高
    data(){
        return{
            x:300,
            y:200,
        }
    },
    // 生命周期 mounted 等挂载函数 混入会执行相同两段代码
    // 来者不拒 均会执行
    mounted(){
        console.log("多次重复执行");
	}
}


// 全局混合
// main.js 中
import {mixin} from "../mixin";
// vm 与 vc 均会执行该函数
Vue.mixin(mixin);

6.插件

聚合代码 书写全局配置

在 src 添加 plugs.js

export default {
    // 该参数 为 Vue的构造函数
    install(Vue,x,y,z){
        // 全局过滤器
        Vue.filter("mySlice",fuction(value){});
    	// 全局指令
    	Vue.directive("fbind",{});
		// 定义混入
		Vue.mixin({});

		// 给Vue原型添加方法 vm 与 vc 均能使用
		Vue.prototype.hello = ()=>{alert("你好啊")};
    }
}

main.js

// 引入插件 
import plugs from "../plugs.js"
// 在声明 vm 之前开启插件
// 能接收多个 参数 但是第一个必须是插件名 install的第一个参数必须为 Vue
Vue.use(plugs,1,2,3)

// 全局声明之后 可在 全部 vm vc 中使用

7.scoped样式 / less 编译

<style scoped>
    /* 加入scoped之后 各个css之间相互独立 不互相影响 */
    /* 一般app组件中 不会使用scoped */
    /* 使css样式局部生效 */
</style>

<style lang="less">
    /* 支持使用less */
    /* 需要安装包 less-loader */
    /* 需要考虑兼容性问题 */
    /* 安装对应版本的 less-loader 不然会报错 */ 
</style>


<style lang="css">
</style>

8.给兄弟组件传参

1.传给父元素 (props传给父元素一个方法)

2.由父元素传给子元素的兄弟元素

(9. 中含其他方法 使用ref与自定义事件 与mounted)

<template>
	<School :receive="receive"></School>
</template>


<script>
    export default{
        name:"Compents",
        methods:{
            receive(x){
                console.log('我是app组件我收到了数据',x)
            }
        }
    }
</script>

School.vue

<script>
    export default{
        name:"School",
        props:["receive"],
        method:{
            add(x){
                receive(x);
                // 可在子元素调用父元素的方法
            }
        }
</script>

9.组件的自定义事件

1.js内置事件 click keyup 等

2.自定义事件

app.vue

<template>
	<Student v-on:atguigu="getStudentName"></Student>
	<Student ref="studnet"></Student>
</template>
<script>
	{
        // 挂载mounted 子传父
        mounted(){
            // $on 当atguigu事件触发的时候
            this.$refs.student.$on('atguigu',this.getStudentName)
        },
        methods:{
			getStudentName(name){
                console.log("获得name数据")
            }
        }
    }
</script>

Student.vue

<template>
	<h1 @click="ad"></h1>
</template>

<script>
	{
        // props:['getStudentName'],
        // 触发事件 子传父
        methods:{
            ad(){
                // 触发事件 使用方法 $emit
                this.$emit('atguigu',this.name)
            },
        }
    }
</script>

10.解除绑定自定义事件

Student.vue

<template>
	<h1 @click="unBind"></h1>
</template>

<script>
	{
        methods:{
            unBind(){
                // 触发事件 使用方法 $emit
                this.$emit('atguigu',this.name)
                // 解绑单个自定义事件
                this.$off('atguigu')
                // 解绑多个自定义事件
                // 传入数组
                this.$off(['atguigu','...','...'])
                // 解绑全部自定义事件
                this.$off()
               	// 摧毁 vc实例 自定义事件解绑(全部失效)
                this.$destroy()
            },
        }
    }
</script>

11.全局事件总线

设计一个不在任何组件内的组件 作为全部事件的中转站

A中触发自定义事件 中转X 触发C的操作

// 条件

//在所有组件都能访问的地方添加 数据对象

// 可以使用 $on $off $emit

1.windows 2.VueCompents(需要改原型)

使用 Vue 在main.js中操作

VueCompent对象的____proto____指向Vue的原型对象

// 在main.js 中添加 'X' 傀儡 作为 vm / vc 可以使用 $on $emit $off
// 则傀儡必须为 Vue 实例 vm
 
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  el:"app",
  render: h => h(App),
  beforeCreate(){
    Vue.prototype.$bus = this; //全局事件总线
  }
}).$mount('#app')


// 在其他 vc 中使用全局事件总线
	{
        methods:{
            unBind(){
                // 触发事件 使用方法 $emit
                this.$bus.$emit('atguigu',this.name)
                
                // 解绑全部自定义事件
                this.$bus.$off()
               	// 摧毁 全局事件总线 vm 实例 自定义事件解绑(全部失效)
                this.$bus.$destroy()
            },
        },
        beforDestroy(){
            // 在在被摧毁之前解绑该组件 在总线中的事件
            // 解绑单个自定义事件
                this.$bus.$off('atguigu')
                // 解绑多个自定义事件
                // 传入数组
                this.$bus.$off(['atguigu','...','...'])
            }
    }

image.png

12.消息订阅与发布

/*
消息订阅与发布
	1.订阅消息︰消息名
	2.发布消息︰消息内容
*/

// 需要使用 消息订阅与发布的库
// 在各种框架里都能使用 不局限于 vue 
// 有多种库存在 消息订阅与发布是一种理念
// 这里推荐 : pubsub-js 

// 类似于 $bus

// 订阅消息
import pubsub from 'pubsub-js'
// 在mounted中订阅
// 需要设置id							// 非vue管理必须使用箭头函数!!
const this.pubid = pubsub.subscribe("消息名",fuction(msgName,data){
	// msgName 为消息名 
    // data 为之后的传递的参数
})
// 或者传入 在 methods 中配置的方法 this 不会出问题
const this.pubid = pubsub.subscribe("消息名",this.method);

// 在销毁前取消丁订阅 beforDistory
pubsub.unsubscribe(this.pubid);

// 发布消息
pubsub.publish('hello',666);

13.$nextTick

在DOM节点 下一次更新之后 执行回调函数

this.$nextTick(()=>{
    this.$refs.editInput.forEach((element)=>{
    element.focus();
	})
)}
  • 作者:lonelysnowman
  • 原文链接:https://blog.csdn.net/lonelysnowman/article/details/124871299
    更新时间:2022-12-31 14:28:25