尚硅谷:https://www.bilibili.com/video/BV1Zy4y1K7SH?p=53
组件化编程
如何定义、创建组件
1、非单文件组件
2、单文件组件
非单文件组件
基本使用
组件就是一块砖,哪里需要哪里搬!
为什么data对象必须使用函数返回值?
x1修改后,x2的值也会跟着变!!! 因为(x1与x2)使用的是同一个对象地址!
x1修改后,x2的值就不会跟着变了!
全局组件与局部组件
1、定义组件
const school = Vue.extend({name:school,data(){return{msg:"aa"}},template:`<div>hello {{msg}}</div>`})
2、注册组件
局部注册组件
new Vue({el:'#id',data:{msg:"aa"},compontents:{school}})
全局注册组件
Vue.compontent("school",school)
3、使用组件
<school></school>
注意点
1、组件名称的定义
(1)一个单词组成,可以使用小写单词,定义和使用是一样的--->(school)
(2)一个单词组成,可以使用首字母大写的单词,定义和使用一样,与开发者工具呼应。--->(School)
(3)多个单词组成,可以使用全小写,但是中间加"-",--->(my-school)
(4)多个单词组成,可以把每个单词首字母大写,(但是需要vue脚手架工具)
组件中的name属性,可以定义组件在开发者工具中的命名。
组件的嵌套
vm管理APP,APP管理其他组件!(application)
注意组件的开发顺序,如果该组件调用了其他组件,必须放到调用组件创建之后,否则会报错!!!
VueComponent
在页面解析组件标签的时候,vue自动创建了组件的实例对象!!!
每次调用Vue.extend()的时候,都返回一个新的VueComponent对象!
image.png
一个重要的内置关系
vm、vc区别: el不一致,data不一致
vm有el,data:{}
vc没有el,data(){return{}}
组件是可复用的 Vue 实例
因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。
一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
单文件组件
单文件命名范例
为了识别vue文件,vscode需要安装插件:vetur
非单文件组件最大的问题就是:样式不能随着组件移动而移动。(编写,引入,复用不太方便!)
单文件组件的页面结构
单文件组件的页面结构
template不参与编译的,最后页面显示的就是template里面包含的内容,所以里面包含的必须是一个节点,而不能是多个。
es6模块化概念
导出的三种方法以及对应的导入方法
多行暴露
export function aa1(){
console.log('分别导出1');
}
export function aa2(){
console.log('分别导出2');
}
//解构赋值(导入)
import { aa1 , aa2 } from 'a.js'
统一暴露
function bb1(){
console.log('综合导出1');
}
function bb2(){
console.log('综合导出2');
}
export {bb1,bb2}
//解构赋值(导入)
import {aa1,aa2} from 'b.js'
默认暴露
export default function cc(){
console.log('默认导出');
}
//使用定义变量(导入)
import c from 'c.js'
c.cc()
使用vue脚手架
开发语言(vue核心技术) /////// 标准化开发工具(脚手架CLI)
脚手架版本一般是向下兼容的,
所以使用vue2 + 脚手架4.是可以的,
尽量少的时候vue3 + 脚手架1, 这样是不合理的!
CLI: commont line interface 命令行接口工具(官网地址:https://cli.vuejs.org/zh/)
es6转es5,最出名的就是babel
代码检测,eslint
// 配置淘宝镜像
npm install -g cnpm --registry=https://registry.npm.taobao.org
// 安装脚手架工具
npm install -g @vue/cli
//创建项目
vue create my_test
//进入目录并启动项目
cd my_test
npm run serve
//两种访问方式
本地: localhost:8080
局域网内: 10.100.40.109:8080
分析脚手架结构
vue引入的时候,默认是引入的残缺版的vue,是没有模板解析器的vue!!!(不能解析template)
可以自定义引入路径,就可以正常使用了
import Vue from 'vue'
import Vue from 'vue/dist/vue.js'
render(createElement){
return createElement("h1","你好呀")
}
不断精简优化代码
优化1:render:(createElement)=>{return createElement("h1","你好呀")}
优化2:render:createElement=>createElement("h1","你好呀")
优化3:render:h=>h("h1","你好呀")
优化4:render:h=>h(App)
// vue会自动调用render函数,render函数会执行createElement函数,创建元素,并返回。
vue包含2部分内容:
1、核心(生命周期,数据,函数等)
2、模板解析器(占有vue代码的1/3)
在开发的时候,使用全的vue没什么问题,
但是在开发完成后,通过webpack打包后,已经把vue代码转换为js文件,就没有必要再使用vue的模板解析器,所以就出来了精简版的vue。
vue在创建项目的时候就引入了vue-template-compiler模板解析器,专门用来解析.vue结尾的文件
.js结尾的文件中出现的template是不会被解析的!所以替换写法,使用render函数。
获取 vue中webpack默认配置文件方法
vue inspect > output.js
使用vue默认配置时,不能修改的文件或者文件夹
vue 配置参考项: https://cli.vuejs.org/zh/config/
vue.config.js 与webpack默认的配置进行合并,
webpack打包,使用的是nodejs
module.exports = {} 使用的不是es6的暴露,使用的是commondjs的暴露!
修改了vue.config.js配置文件,必须重启才能生效!
webpack的loader,都可以做语法检查的!
image.png
ref属性
ref 与 id 对于元素没有什么区别,但是在vue中还是使用ref最好(id替代者)! 获取的是真实dom
但是对于组件就有很大的区别。获取的是组件实例对象!
使用的时候用 this.refs.id)即可!
props配置项
组件使用的时候传值
组件定义的时候要去接收值,使用props
props的三种接收方式
1、简单的声明接收
2、对接收的数据进行类型限制
3、接收数据的同时:进行类型限制+默认值指定+必要性限制。
接收到的props中的值,在子组件中,是不可修改的!!!
data中的数据的优先级低于props中传入的值!
先获取props中的数据,再定义data中的数据,最后渲染到页面中。
mixin配置项(混入、混合)(本质是一个对象,对象里是公共属性)
2个(多个)组件,使用相同的配置方法的时候,提取公共的代码,生成一个js代码,并引入
混入(mixin) :把2个或多个对象的属性进行重新整合!以如果有重复,就以你以前的数据为主!
属性和方法都是以自身的数据为主,
但是 钩子函数,却是要把内部的数据全部合在一起,混合的数据在前面,自身的代码在后面。
局部混合:mixins:[]
全局混合:Vue.mixin()
插件
混入(对象,minix.js)
插件(对象,必须包含install方法,plugins.js)
插件传入的参数是vue的缔造者(构造函数)Vue可以做很多事情!
插件中的install,是Vue帮我们调用的!
scope(css代码作用域)
scope(范围) scoped 原理:通过class + [随机属性] 确定class样式显示
查看less-loader版本: npm view less-loader versions
安装指定版本的命令: npm i less-loader@7
less-loader8以上都是为webpack5服务的
TodoList案例
把 普通网页(html,css,js)转化成组件化(vue,vuecomponent)代码的能力
开发思路
父子组件传值的最普通的方法
1、父给子传值:
父页面的子组件传对象,子组件使用props接收
2、子组件给父组件传值
父页面给子组件传方法,子组件使用props接收方法,子组件修改值的时候,调用props里父组件的方法,实现父页面值的改变!!!
数据在哪里,操作数据的方法就写在哪里!
修改选择状态的2种方法
1、通过v-model实现 ((todo.done)不推荐!)
2、通过显示(:checked="todo.done")和change或click(id)方法实现
image.png
修改的概念
let a = 1; a= 2; 是修改
let obj = {a:1,b:2} obj.a = 99; 是值的修改,引用不变!(vue监测不到)
let obj = {a:3,b:5} obj = {x:1,y:99}; 是对象的修改,地址都变化了!引用改变了!
统计有多少符合条件的数量?
1、使用for循环等方法 (for...in... / for...of... / foreach)
2、使用es6语法 reduce(function(){},0) // 统计
不推荐使用props的值 v-model="props"里面的值
但是如果是计算属性的值,checkbox是可以使用v-model="计算属性的值"
todoList的总结
父组件给孙组件传值,必须逐层传递
子组件给父组件传值,父组件必须先给子组件一个函数!
vue是单向数据流,props传的值是不可修改的!子组件v-model不能是props的值!或者说不推荐!
浏览器的本地存储
localstorage用法
localstorage:本地存储,直接写在本地磁盘上,即使关闭浏览器也存在的!
里面保存的都是以键值对的形式存在(都是字符串),如果不是string类型,会调用toString()方法。
保存对象就会出问题,需提前使用JSON.stringify()转一下,取的时候使用JSON.parse()转一下。
设置值(修改值)
localStorage.setItem("p",JSON.stringify({name:"123"}))
获取值
localStorage.getItem("p")
删除值
localStorage.removeItem("p")
清除全部
localStorage.clear()
如果获取的是不存在的属性,会返回null!
清除localstorage的方法:
1、点击按钮,手动清除
2、手动清除浏览器缓存
sessionstorage
关闭浏览器后,会话就结束了,sessionStorage就会被清除。
原生js 方法的调用 function abc(){} abc()方法调用
把todoList做成本地化存储,重点就是刚进入的时候判断是否为null,设置[]
监控todoList改变,存储到localStorage中,添加的时候使用unshift()方法,普通监听也可实现;
但是因为里面有修改对象的可否选中属性,需要用到深度监听!
组件的自定义事件
js中的内置事件,是给页面元素使用的,
组件的自定义事件,是给组件使用的。
自定义事件的绑定
image.png
v-on 的意思是:给Student组件绑定事件,说的再具体点就是:给Student组件的实例对象(VC)绑定了一个自定义事件,当调用atguigu的时候,就会直接调用demo方法。
事件触发的方式:
click 鼠标点击的时候触发,
keyup 键盘按键抬起时候触发,
那组件的自定义事件怎么触发呢?this.$emit("atguigu",this.name)
2种子组件向父组件传值的方法对比
第一个方法是:传方法,props接收,再调用。
第二个方法是自定义组件方法,不传递方法,只是作为一个回调函数在调用,使用this.$emit("")
调用。
第三种是:给组件定义ref,在mounted()的时候把方法挂载到对应的方法上。once()
组件自定义事件的解绑
// 解绑单个自定义事件
this.$off("atguigu")
// 解绑多个自定义事件
this.$off(["atguigu","atguigu2"])
// 解绑所有自定义事件
this.$off()
函数中,多个参数的接收,使用解构语法,
...abc 最后解构出来的abc,就是一个数组。
箭头函数没有自己的指向,必须向上找;
普通方法有自己的指向,就是调用方法的指向!
组件使用原生的事件方法
@click.native=show
show(){alert(123)}
没有native修饰的时候,就默认为组件的自定义事件,必须使用$emit("click")
触发调用。
全局事件总线
消息订阅与发布
js本身很难实现消息的订阅与发布,需要借助第三方库来实现,推荐使用:pubsub-js
需要数据的人要订阅消息(subscribe)订阅
发布数据的人要发布消息(publish)发布
消息订阅要写在mounted中,在挂载之后就订阅消息。
注意,当组件销毁前要取消订阅,类似于定时器,清除定时器ID。
_参数,表示不使用,只是一个占位符!
判断对象中是否有某个属性,使用obj.hasOwnProperty("isEdit")
代码编写规范
vue中,属性先把原生的放在上面,可以换行显示
外部的引入放在最上面,自己的引入可以往下放置
$nextTick方法的意义,就是在页面渲染完成之后再执行!,里面是一个回调函数。
定时器不给时间,也可以实现延后执行操作dom的操作(定时器里的方法都会被放入到消息队列中),但是最好还是使用官方的api。