第二章 组件化编程
1.什么是模块什么是组件
模块:
一般就是一个js文件
组件:
它是实现一个应用的局部功能的代码和资源的集合
传统方式编写的话:分为html、css、js
它们的代码复用性不高 、 依赖关系混乱、不好维护
组件:
细分为一个一个的局部的功能,里面包括了代码和资源,提高代码的复用性。
2.组件的基本使用
1.创建组件使用
Vue.extend({}) 注册时传入的对象 和vm中的几乎一样 只是data要写成函数的形式 然后不能写el
2.注册组件
可以在vm中使用components{}注册
注意:
组件的数据要写成函数的形式 ,这样 不会产生连带效果
也可以使用全局注册 Vue.component(‘组件名’,组件)
3.使用就是 用组件名的标签
非单文件组件:
一个文件可以包含多个组件
组件里不可以包含el
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>el data 的两种写法</title>
<!-- 1.引入js依赖 -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 2.给定一个容器 -->
<div id="root">
<!-- 3.使用就是 用组件名的标签 -->
<person></person>
<hr/>
<!-- <school></school> -->
</div>
<script type="text/javascript">
Vue.config.productionTip = false; // 3.关闭生产环境提示
// 1.创建组件
const a = Vue.extend({
template:`
<div>
<h1>我是{{name}}</h1>
</div>
`,
data(){
return {
name:'zhansgan'
}
}
})
const school= Vue.extend({
template:`
<div>
<h2>我在{{school}}</h2>
</div>
`,
data(){
return {
school:'湖南'
}
}
})
// 全局注册
Vue.component('person',person)
// 4.使用Vue操作这个容器
new Vue({
el:'#root',
//可以在vm中使用components{}注册
// components:{
// person:a
// school
// }
})
</script>
</body>
</html>
3.组件的几个注意点
1.组件命名的时候
如果有多个单词可以用 - 隔开,但是在注册是时候要用 ’ ’ 引用
也可以使用大驼峰命名法 (但是这个只能在脚手架环境用)
components:{
'ce-shi':zijian
}
2.在命名的时候不要用html已经预留了的标签
3.Vue.extend({}) 可以简写为 {} 的形式 Vue在注册组件的时候还是会调用extend的
4.在定义组件的时候可以使用name来指定组件名在开发者工具的样子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>el data 的两种写法</title>
<!-- 1.引入js依赖 -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 2.给定一个容器 -->
<div id="root">
<ce-shi></ce-shi>
<ce></ce>
</div>
<script type="text/javascript">
Vue.config.productionTip = false; // 3.关闭生产环境提示
const zijian= Vue.extend({
// name:'xiao',
template:`
<div>
<h1>wishing</h1>
</div>
`,
})
const obj={
template:`
<h1>wo</h1>
`
}
Vue.component('ce',obj)
// 4.使用Vue操作这个容器
new Vue({
el:'#root',
components:{
'ce-shi':zijian
}
})
</script>
</body>
</html>
4.组件的嵌套
规范,,
vm管理—app组件 在app组件中再往下去管理组件
组件嵌套
是可以在一个组件的创建中去components另一个组件,在template中使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>el data 的两种写法</title>
<!-- 1.引入js依赖 -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<!-- 一般规范
vm管理---app组件 在app组件中再往下去管理组件
-->
<body>
<!-- 2.给定一个容器 -->
<div id="root">
<!-- <app></app> -->
</div>
<script type="text/javascript">
Vue.config.productionTip = false; // 3.关闭生产环境提示
// 定义学生组件准备嵌套
const student = Vue.extend({
name:'student',
template:`
<div>
<h1>我的名字是{{name}}</h1>
<h2>w我的年龄是{{age}}</h2>
</div>
`,
data(){
return {
name:'张三',
age:20
}
}
})
const school=Vue.extend({
name:'school',
template:`
<div>
<h1>这个学校是{{name}}</h1>
<h2>地址{{address}}</h2>
<student></student>
</div>
`,
data(){
return {
name:'科技大学',
address:'长沙'
}
},
// 在这个组件中注册嵌套组件 在模板中使用
components:{
student:student
}
})
const pin=Vue.extend({
template:`
<div>
<h1>平级组件</h1>
</div>
`
})
const app = Vue.extend({
template:`
<div>
<school></school>
<pin></pin>
</div>
`,
components:{
school,
pin
}
})
// 4.使用Vue操作这个容器
new Vue({
template:`<app/>`,
el:'#root',
components:{
app
}
})
</script>
</body>
</html>
5.VueComponent构造函数
1.首先我们用Vue.extend它返回的就是Vuecomponent的构造函数,它是Vue帮我们生成的.
2.当我们使用<组件标签>的时候,Vue就会帮我们执行new VueComponent(options)的到实例对象
3.组件中组件所管理的函数中的this都是 组件的实例对象
4.每一个Vue.extend({})都会生成一个新的VueComponent
5.VueComponent简称vc
6.vm中的children就是被vm所管理的组件
7.vc和vm是不同的,但是vc中可以复用绝大部分的vm,现在处理vm中的el可以指定为哪个容器服务不能用在vc外
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>el data 的两种写法</title>
<!-- 1.引入js依赖 -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 2.给定一个容器 -->
<div id="root">
<!-- 当我们使用 组件时 Vue就会执行 VueComponent的构造函数 得到vc实例 -->
<vc></vc>
</div>
<script type="text/javascript">
Vue.config.productionTip = false; // 3.关闭生产环境提示
// 这个vc 就是我们的Vuecomponent实例对象
const vc= Vue.extend({
template:`
<div>
<h1>{{name}}</h1>
<button @click='test'>点我</button>
</div>
`,
data(){
return {
name:'张三'
}
},
methods: {
test(){
// VueComponent中使用this 是指的VueComponent实例对象 (使用普通方法)
console.log('名字是',this.name)
}
},
})
console.log(vc)
// 4.使用Vue操作这个容器
new Vue({
el:'#root',
components:{
vc
}
})
</script>
</body>
</html>
6.重要的内置关系
Vue让
vuecomponent的原型对象的原型对象指向了Vue的原型对象
VueComponent.prototype._proto==Vue.prototype
这样可以让vuecomponent实例可以访问到Vue原型上的方法和属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>el data 的两种写法</title>
<!-- 1.引入js依赖 -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 2.给定一个容器 -->
<div id="root">
<vc></vc>
</div>
<script type="text/javascript">
Vue.config.productionTip = false; // 3.关闭生产环境提示
Vue.prototype.x=99; // 把属性放在Vue的原型对象上 vuecomponent实例对象可以访问得到
const vc=Vue.extend({
template:`
<div>
<h1>{{name}}</h1>
<button @click='dian'>点我访问</button>
</div>
`,
data(){
return {
name:'zhansgan'
}
},
methods:{
dian(){
alert(this.x)
}
}
})
console.dir(vc)
// 4.使用Vue操作这个容器
new Vue({
el:'#root',
components:{
vc:vc
}
})
</script>
</body>
</html>
function Dome(){
this.s=10
}
const d= new Dome()
// Dome.prototype 在函数上的原型 是显示原型对象 我们一般往显示原型对象上加东西
// d.__proto__ 实例上的是 隐式原型对象
// 不管是类的原型 还是实例的原型都是同一个
console.log(Dome.prototype === d.__proto__)
7.单文件组件
1.一个.vue文件就是一个单文件组件
2.它里面包含了 template(结构)只能有一个根元素、 script(交互数据) style(样式)
3.组件就需要暴露
1.export const zujian 这样就是分别暴露
2.在script 的最下方 用 export {zujian} 这样就是统一暴露
3.export default zujian 这样就是 默认暴露
引入组件
import 组件名 from 位置
import {} from 位置
导入多个 用,隔开
代码组件
需要暴露 以后才可以被引入
<template>
<div class="demo">
<h1>学校的名字{{name}}</h1>
<h2>学校的地址{{addrees}}</h2>
<button @click="dian">点我弹出学校名</button>
</div>
</template>
<script>
export default Vue.extend({
name:'School',
data(){
return {
name:'东方',
addrees:'湖南'
}
},
methods: {
dian(){
alert(this.name)
}
},
})
</script>
<style>
.demo{
background-color: yellow;
}
</style>
App 管理所有的组件 在script最上边引入组件
<template>
<div>
<School></School>
<Student></Student>
</div>
</template>
<script>
// 1.导入组件到App文件中 由App来管理所有组件
import School from './School.vue'
import Student from './Student.vue'
// 2.在App中注册所有组件
// 3.在模板中使用
Vue.extend({
name:'App',
components:{
School,
Student
}
})
</script>
main.js创建Vue指定为哪个容器服务,注册app组件
import App from './App.vue'
// 这个是一个入口文件 只要管理App 在这里创建Vue 指明为哪个容器服务
new Vue({
el:'#root',
components:{
App
}
})
页面 引入js、main.js 使用组件app
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>练习一下 单文件组件</title>
</head>
<body>
<!-- 2.给定一个容器 -->
<div id="root">
<App></App>
</div>
<!-- 引入文件在body的最下方去引入 先让模板出来 在去解析 -->
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript" src="./main.js"></script>
</body>
</html>
第三章使用Vue脚手架
1.初始化脚手架
脚手架是vue cli 命令行接口 ,它是Vue的标准化开发工具
官方文档
文档: https://cli.vuejs.org/zh/。
脚手架的安装
1.如出现下载缓慢请配置 npm 淘宝镜像:npm config set registry
https://registry.npm.taobao.org
2.全局安装@vue/cli。
npm install -g @vue/cli
3.切换到你要创建项目的目录,然后使用命令创建项目
vue create xxxx (这个名字要小写、多个单词用_隔开)
4.启动项目
npm run serve
出现问题安装Vue脚手架版本与node版本不对应
You are using Node v10.14.2, but this version of @vue/cli requires Node ^12.0.0 || >= 14.0.0
解决
1.执行卸载命令删除当前vue-cli: cmd窗口输入:npm uninstall -g @vue/cli
2、执行如下命令安装低版本的: npm install -g @vue/cli@4.5.13
3、在cmd中执行:vue -V 命令;展示成功。
2.脚手架文件目录说明 (Vscode开启中断 Ctrl+~)
1…gitignore 忽略文件
2.babel.config.js ES6转化为ES5需要的文件
3.符合npm规范的就会包含
package.json 包的说明书
package-lock.json 包版本控制文件
4.README.md 整个工程进行一个说明描述
5.src
assets(条件资源)放静态资源的
除了App组件 components中放入其他组件
App.vue 管理器它组件的
main.js 服务运行启动的入口
6.public
favicon.ico 网站的页签图标
index.html 页面咯
3.render说明 和Vue完成版和精简版
/*
该文件是整个项目的入口文件
*/
//引入Vue 这里引入的是 运行时的vue 没有模板解析器 所以不能解析Vue
// 当然你也可以引入完整版的Vue vue/dist/vue.js
import Vue from 'vue'
//引入App组件,它是所有组件的父组件
import App from './App.vue'
//关闭vue的生产提示
Vue.config.productionTip = false
/*
关于不同版本的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函数去指定具体内容。
*/
//创建Vue实例对象---vm
new Vue({
el:'#app',
//render函数完成了这个功能:将App组件放入容器中
render: h => h(App),
// render:function(createElement){ 完整的写法 createElement是一个函数 参数是 标签名内容
// return createElement('h1','你好呀')
// }
// render:q=> q('h1','你好啊')
// template:`<h1>你好啊</h1>`,
// components:{App},
})
4.修改和查看默认配置
1.Vue的默认配置是隐藏的不会显示的
2.使用
vue inspect > output.js 查看
修改的话得在package.json 包说明文件同包下创建vue.config.js配置文件
去官网查找文档
https://cli.vuejs.org/zh/
module.exports = {
pages: {
index: {
// page 的入口
entry: 'src/main.js'
},
},
lintOnSave:false // 关闭语法检查
}
5.ref属性 给元素或者子组件注册引用信息
<template>
<div>
<h1 ref="title">欢迎您</h1>
<school ref="biaoqian"></school>
<button @click="dian">点我获取标签</button>
</div>
<!-- 总结
ref标签 和id类似 它是Vue提供的指令
1.放在标签上 我们可以给元素或者子组件注册引用信息
2.放在html上面,拿到的就是真实的DOM元素,在组件上拿到的就是组件实例对象(而id在组件上拿到的是组件的所有标签)
3.通过
ref='名字' 放在上面
this.$refs.名字拿取
-->
</template>
<script>
import School from './components/School'
export default {
name:'app',
components:{
School
},
methods: {
dian(){
console.log(this.$refs.title)
console.log(this.$refs.biaoqian)
}
},
}
</script>
6.props配置 组件用来接收参数
// props这个是用来定义这个组件使用时传递的一些参数
// props:['age','hoppy'] // 这个是简单定义 它只能接收一个字符串信息 而且 也不能对参数类型限制
// props:{ // 这个是第二种限制参数的形式 他可以限定参数的类型
// age:Number,
// hoppy:String
// }
props:{
age:{
type:Number, // 限制参数的类型
require:false, // 限制参数是否必须传递
default:100 // 参数没有传递时的默认值
},
hoppy:{
type:String
}
注意props的优先级是比data中的数据高的
// Vue不建议修改 传递参数属性 但实际可以改 如果要改建议在data中定一个变量来接收参数 修改data中的
dataAge:this.age
this.dataAge++
组件标签传递参数
<!-- 使用组件时传递参数 -->
<!-- <school age="20" hoppy="看风景"></school> -->
<!-- 传递参数的时候可以用v-bind 使得传递参数的时候 是一个表达式执行 -->
<school :age="20+1" hoppy="看风景"></school>
7.mixin混合 组件重复代码的抽取
当混合与data中的数据或者方法冲突的时候,以自己写的为准,但是当出现多个钩子函数的时候,就都会执行
1.在src下写一个mixin.js混合文件
在这个里面直接写对象 但是要暴露
2.在要用的地方先引入混合mixin
3.在mixins:[]注册混合
mixin.js
// 这个是用来把多个组件中的重复代码抽取出来成为一个对象
export const m={
methods: {
dianji(){
alert(this.name)
}
},
}
组件中使用
// 局部引入 这个混合 mixin
import {m} from '../mixin'
export default {
data(){
return{
name:'zhansgan',
age:20
}
},
// 注册混合 使用['',''] ,多个的话用,隔开
mixins:[m]
}
在main.js中
// import {m} from './mixin'
// Vue.mixin(m)
// 引入整个应用都用的混合 全局混合
8.plugin插件 Vue的增强
定义 plugins.js文件
// 插件是Vue的增强,可以在Vue启动前启动插件
// 插件是一个对象的形式,里面写install方法 (第一个参数是Vue,第二个参数是使用的时候传递啥
// 在main.js 创建Vue之前 引入插件 用Vue.use(options)使用插件
export default{
install(Vue){
// 在插件中可以定义一些全局过滤器、全局指令、全局混入等
Vue.filter('jieuq',function(value){
return value.indexOf(0,4)
})
// 自定义指令
Vue.directive('fbind',{
bind(e,v){
e.value = v.value
},
inserted(e){
e.focus()
},
update(e,v) {
e.value = v.value
},
})
// 全局混入
Vue.mixin({
data(){
return {
a:'111'
}
}
})
// Vue原型上的方法 插件都可以使用
Vue.prototype.hello = ()=>{alert('插件好')}
}
}
在main.js中使用插件
// 引入插件
import plugins from './plugins'
// 使用插件 后面还可以传递参数
Vue.use(plugins)
用插件中的方法
<template>
<div>
<!-- 插件过滤器 方法 指令的使用 -->
<h1>我的名字是{{name | jieuq}}</h1>
<h1 @click='dian'>我的年龄是{{age}}</h1>
<input type="text" v-fbind='name'>
</div>
</template>
9.scoped样式范围
首先每一个组件的style 要是没有写上scoped的话,那么默认是把他们编译在一起的,这样就会有一个重名冲突
会后引入的会覆盖前引入的
在<style scoped 加上的话 他会给用到样式的标签加上一个属性(自动生成) 而在css中会使用[属性名]去控制
style lang=‘css/less’ 默认是css
在App写的样式全局可用 那你就不要写scoped
<style scoped>
/* 在<style scoped 加上的话 他会给用到样式的标签加上一个属性(自动生成) 而在css中会使用[属性名]去控制
.demo[data-v-22321ebb] {
background-color: pink;
}
*/
.demo{
background-color: pink;
}
</style>
10.TODO list小案例
组件化编码流程(通用)
1.实现静态组件:抽取组件,按功能点去拆分,使用组件实现静态页面效果
这里要自己想到怎么分组件 与 命名
2.展示动态数据类型
数据的类型是什么,名称是什么
数据存在哪个组件中:
一个组件再用就放到自身中
多个组件在用就放到多个的父组件中(状态提升)
3.实现交互,绑定事件开始
使用在list存数据的话:
数据是[ {},{}] 的结构
选择框动态选中使用:checked=‘’
<input type="checkbox" :checked="todo.done"/>
参数和传递
使用v-bind才可以使用 表达式啊啊啊
<Myitem v-for="todoobj in todos" :key="todos.id" :todo="todoobj">
data(){
return {
todos:[
{id:'001',context:'吃饭',done:false},
{id:'002',context:'睡觉',done:true},
{id:'003',context:'打游戏',done:false},
]
}
}
初级组件间通讯
1.App—》子组件 可以通过直接在组件标签中写参数 子组件用props接收
2.子组件往App中传递参数
首先App往子组件传递一个方法 带参数 子组件在需要的地方调用父组件的方法,传递参数 就可以在父组件中使用子组件的参数了
方法也是传递方法名 接收也是用方法名
父组件:
<Myhead :addTodo="addTodo"></Myhead>
methods:{
addTodo(todoobj){
// 这个方法传递给子组件,参数用子组件来传递
// 数组使用方法来 使得数据监测成功
this.todos.unshift(todoobj)
}
子组件:
props:['addTodo'], 接收
this.addTodo(todoobj) 在vc中调用
选择框数据的变换
传递参数可以传递方法
v-model如果是checkbox 那么v-model如果是一个bealoon值的话就是比绑定checked
指定的语法
v-XX:属性名=‘属性值’
v-model为啥操作props了还没有报错 是因为Vue值监控了对象一层,没有监视对象内部属性的变换
props传递对象,在props中修改对象内部值,竟然data中的数据也改变了
<!-- 这种是把数据传递给App,让app去修改data中的数据 而不是修改props -->
<input type="checkbox" :checked="todo.done" @change="gaibian(todo.id)"/>
<!-- 这种直接通过 v-model去修改 props的数据了 不推荐用 -->
<input type="checkbox" v-model="todo.done"/>
App中的
changedone(id){
// 去遍历数据得到 具体是哪个todo 把那个todo的done数据该掉
this.todos.forEach((todo)=>{
if(todo.id === id){
todo.done = !todo.done
return;
}
})
删除按钮的实现,和底部的统计reduce数组函数
1.li:hover {background}这个是 选中加深颜色
li :hover{
background-color: darkgray;
}
li:hover button{
display:block
}
2.点击删除按钮,就把id传递给App组件,让App去过滤删除
shandelete(id){
// 用过滤来删除
this.todos = this.todos.filter((x)=>{
return x.id !== id
})
底部统计用数组的 reduce函数
动态计算属性 选中有多少个
computed:{
sizeDone(){
// 数组的统计函数 reduce 它第一个参数是函数 两个参数 一个是统计前一个的值 另一个是数组当前遍历值
// 数据有多少就会执行多少次 reduce 最后一次执行的返回值就是 reduce的返回值
// 第二个参数是 初始统计值
return this.todos.reduce((pre,cur)=>{
return pre+(cur.done ? 1 : 0)
},0);
}
}
底部全选按钮的实现 和 清除
1.可以接收用户输入,并且想要有初始化值和改变值 那么可用v-model
不用v-model实现全选按钮:
1.初始化 全选按钮的选中和不选中 就是选中的等不等于全部的
<input type="checkbox" :checked="allcheck" @change="changecheck">
todosize(){
return this.todos.length
},
allcheck(){
// 一个计算属性是可以有另外的计算属性计算得来的
return this.sizeDone === this.todosize
}
2.点击全选,要把数据全选或者全取消 通知App修改数据
changecheckapp(isall){
this.todos.forEach((x)=>{
x.done = isall
})
}
methods:{
changecheck(e){
this.changecheckapp(e.target.checked)
}
}
使用V-model:
1.把v-model绑定为一个 初始就是选中的等不等于全部的值 改变的话,就会使用set方法区修改数据
<!-- 通过双向绑定一个计算属性 在计算属性中 使用 get set方法的话就要去修改app中的数据 -->
<input type="checkbox" v-model="allcheck">
allcheck:{
// 一个计算属性是可以有另外的计算属性计算得来的
get(){
return this.sizeDone === this.todosize
},
set(value){
this.changecheckapp(value)
}
}
清除选中,用过滤
cleartodos(){
// 点击这个直接让app去过滤选中的按钮就可以
this.clearto()
}
app中:
clearto(){
this.todos= this.todos.filter((x)=>{
return !x.done
})
}
修改按钮的实现todo.hasOwnProperty(‘isedit’) 判断一个对象内是否有这个属性
1.需要增加一个修改按钮,并且控制一下修改按钮的显示
<!-- <input type="checkbox" v-model="todo.done"/> -->
<span v-show="!todo.isedit">{{todo.context}}</span>
<!-- 增加一个输入框 -->
<input v-show="todo.isedit" type="text" @blur="editDone(todo.id,$event)" :value="todo.context">
<button v-show="!todo.isedit" class="btn btn-edit" @click="editTitle(todo)">修改</button>
2.需要新增一个输入框,当点击修改时,显示输入框,隐藏span,失去焦点blur的时候,把用户输入的数据放入,在隐藏输入框,显示span
editTitle(todo){
// 给这个对象新增一个控制编辑的属性
if(!todo.hasOwnProperty('isedit')){
console.log('新增执行了')
this.$set(todo,'isedit',true)
}else{
todo.isedit = true
}
},
editDone(id,e){
if(!e.target.value.trim()){return alert("输入不能为空")}
// 修改完成失去焦点 要把用户输入的值 写入数据 并且 把isedit置为false
this.$bus.$emit('editdata',id,e.target.value)
this.todo.isedit = false
}
在vuemounted中去绑定事件 // 修改title
this.$bus.$on('editdata',(id,value)=>{
this.todos.forEach((todo)=>{
if(todo.id === id){
todo.context = value
return;
}
})
})
11.浏览器本地存储
1.localstorage 本地存储 除非你手动清除 不然一直在
2.sessionstorage 会话存储 打开浏览器就是一次会话 关闭就没有了
四个API:
// cookie key和value都是字符串
sessionStorage.setItem('msg','我是帅')
localStorage.getItem('msg')
sessionStorage.removeItem('msg')
sessionStorage.clear()
JSON.parse
JSON.Stringify
12.利用本地存储保存ToDo案例中的数据
变量 = 值(为null)的话 || 【】就去后面这个值
1.首先要把Todo中的数据初始化为空
// 这个的意思是前面为真可以用那我就用 没有用那就只能用[]后面的
todos:JSON.parse(localStorage.getItem("todos")) || []
2.当添加的时候在往浏览器中加入数据
watch:{
// 监控todos数据 改变 就往浏览器中存
// 现在watch没有监测到 对象里面的值的改变 所以要开启深度监视 deep
todos:{
deep:true,
handler(value){
localStorage.setItem("todos",JSON.stringify(value));
}
}
}
也就是我们可以启用watch监视来达到效果
13.自定义事件的基本使用 this.$emit(‘事件名’,this.name)
1.首先要给标签绑定自定义事件(两种)
1. v-on:事件名=‘事件函数’
2. 通过ref=‘名字’ 在通过this.$refs.名字.$on('事件名',函数)
ref它写在html标签上的话 就是this.$refs.名字取得真实的DOM的元素
写在组件上的话, 就是获取组件实例对象
2.在绑定了事件的组件中,使用this.$emit(‘事件名’,参数)去触发
在接收参数的时候如果后面有多个参数想要一起接收可以使用
…param可以使用这个来接收所有参数,得到一个数组
<!-- <Student v-on:jin="sendStudentName"></Student> -->
<!-- 第二种通过ref来绑定 -->
<Student ref="student"></Student>
事件函数:
methods:{
getSchoolName(name){
alert(name)
},
sendStudentName(name){
alert(name)
}
},
mounted(){
// 挂载完成 就给student加上自定义事件
this.$refs.student.$on('jin',this.sendStudentName)
}
事件绑定在谁身上就要由谁触发
methods:{
getName(){
this.$emit('jin',this.name)
}
}
这个$方法名一般是在对象上,类上是直接方法名
14.销毁自定义事件(事件在哪个身上由哪个销毁)
通过
this.#off(‘事件名’) 或者[‘’,‘’]数组的形式 或者直接销毁全部不写参数
注意这个组件destroy之后那么这个组件上的watch和这个组件的子组件和自定义事件都会被销毁
让事件只执行一次就是在这个后面加上一个once
<Student v-on:jin="sendStudentName" @test.once="m1"></Student>
15.自定义事件的总结
注意事项:
- 在组件标签上要想使用原生事件那么就要在事件后加 .native来说明,不然会被当做一个自定义事件 ,而且这个事件会加载组件的最外层元素上。
<Student @click.native="add"></Student>
- 使用ref来在mounted挂载完成获取组件实例对象来绑定事件的时候,后面的这个回调函数如果写的是普通函数,那么它的this是 谁调用的谁是 要写成箭头函数的话就会往外找
mounted(){
// 挂载完成 就给student加上自定义事件
this.$refs.student.$on('jin',(name)=>{
console.log('事件被执行了',name,this)
})
}
16.全局事件组件 : 任意组件之间通讯
全局事件总线是基于这个自定义事件的
实现有两个要求
1.x要全部的组件都可以看见
vc的实例对象都可以访问到Vue原型上的属性和方法
Vueconponent.prototype._proto==Vue.protopyte
所以可以放在Vue的原型上
1在main.js上
// 把数据放在Vue的原型上 ,所有组件实例就都可以访问了
Vue.prototype.x=100
2.器他组建访问
mounted(){
console.log("Student",this.x)
}
因为放在这个Vue原型对象上的傀儡需要访问到$on$emit$off 这些都是原型对象上的动西,所以这个傀儡要是一个 VM或者VC
VC:
在main.js中
const x = Vue.extend({}) 得到vuecomponent的构造函数
const vc=new x()
Vue.prototype.x = vc 这样就好了
使用:
在需要用到别人传递来的参数的组件中,通过$on给这个傀儡绑定事件,另外在这个组件被销毁前beforedestroy,要解绑傀儡身上的自定义事件 $off
// 把数据放在Vue的原型上 ,所有组件实例就都可以访问了
// Vue.prototype.x=100
// 定义傀儡
// const x = Vue.extend({})
// const vm = new x()
// Vue.prototype.$bus=vm
// 优化为 直接使用vm
new Vue({
el:'#app',
render: h =>h(App),
// 在只有事件 生命周期刚开始的时候 就给这个Vue绑定
beforeCreate(){
Vue.prototype.$bus=this
}
})
在要用到传递参数的组件上,通过$emit触发这个事件 传递参数
要用到参数的组件上
mounted(){
// 组件挂载完成给 傀儡绑定事件
this.$bus.$on('hello',(name)=>{
console.log("组件间任意通讯被触发了",name)
})
},
beforeDestroy(){
// 组件销毁前 解绑自定义事件
this.$bus.$off('hello')
}
传递参数的组件上
methods:{
sendStudentName(){
this.$bus.$emit('hello',this.name)
}
}
17.消息的订阅与发布:任意组件之间通讯
添加额外的库 pubsub(publish、subscribe).js发布订阅
使用步骤:
1.安装pubsub.js npm install --save pubsub-js
2.引入pubsub-js
import pubsub from 'pubsub-js'
3.在要用到数据的地方 订阅消息 通过pubsub对象.subscribe(消息名,回调函数) 这个回调函数第一个参数是消息名 第二个才是传参
在发消息的地方通过 publish(‘消息名’,参数)去发送消息
发消息
pubsubAge(){
// 通过pubsub.js 发送消息
pubsub.publish('getAge',this.age)
}
收消息
// 订阅消息 这个订阅消息会返回一个 消息id 用来撤销消息
this.pubid = pubsub.subscribe('getAge',(msgName,age)=>{
// 要写箭头函数 这里的this才是 vc 不然就是undifand
console.log('我收到消息了',msgName,age)
})
// 组件销毁前 撤销订阅消息
pubsub.unsubscribe(this.pubid)
如果不想用到参数中的某个参数可以用_代替站位
18.Vue实例上的$nextTick
1.他的作用是:
当我们对数据进行修改操作时,我们要对新的DOM元素进行操作的时候,那么我们可以在nextTick上指定回调函数,那么这个函数会在DOM更新完成后调用
语法:
this.$nextTick(回调函数)
// 获取焦点 这个nexttick 在下一次更新完成DOM元素后被调用
this.$nextTick(function(){
this.$refs.editFocus.focus()
})
19.Vue动画效果(不太了解)
1.transition(过度转变) 包裹住标签动画 transition最终会没有的
首先你要在用
<tansition 去包住标签 可以在这个上面使用name
使用样式去控制标签
<template>
<div>
<!-- 用transition 来标注一个标签 他只能包一个根元素的标签 多个的话要transition-group 每一个标签要加:key
appear属性表示 开始来显现动画 -->
<transition name="hello" appear>
<h1 v-show="qie">我的名字是{{name}}</h1>
</transition>
<button @click="qie = !qie">点我来回切换</button>
</div>
</template>
<script>
// eslint-disable-next-line no-unused-vars
const a = function(){
}
export default {
name:'Test',
data(){
return{
name:'zhansgan',
qie: true
}
},
}
</script>
<style>
h1{
background-color: green;
/* transform: 1s linear; */
}
/* 动画效果的话要配置样式 transition要是没有写name 就会直接用v来控制 全部
.hello-enter 表示进入的起点 .hello-leave-to离开的终点
hello-enter-to, 表示进入的终点
hello-enter-active 表示进入的过程中
*/
.hello-enter,.hello-leave-to{
transform: translateX(-100%);
}
.hello-enter-to,.hello-leave{
transform: translateX(0);
}
.hello-enter-active,.hello-leave-active{
transform: 3s linear;
}
</style>
20.集成第三方动画
1.使用上npmjs.com这个网站
2.搜索animate.css这个网站
1.安装animate这个动画样式
npm install animate.css --save
2.引入这个样式
import “animate.css”
3.使用api
<!-- 用transition 来标注一个标签 他只能包一个根元素的标签 多个的话要transition-group
appear属性表示 开始来显现动画 -->
<transition name="animate__animated animate__bounce" appear
enter-active-class="swing"
leave-active-class="backOutUp"
>
<h1 v-show="qie">我的名字是{{name}}</h1>
</transition>