组件注册
-
局部组件
-
创建一个组件.vue
-
引入:import Mycomp from './components/Mycomp.vue'
-
注册组件export default { name: 'App', components: {
Mycomp
}}
-
使用组件<Mycomp></Mycomp>
-
-
组件组成
-
template 视图
-
script 逻辑
-
style 样式
-
-
全局组件
-
注册全局组件 在Vue对象身上有个Vue.component() 注册全局组件 在所有的组件中 不需要引入 可以直接使用
-
语法:Vue.component('my-component-name', {
// ... 选项 ...
})
-
代码演示
// import Vue from 'vue'//运行时:vue.runtime.js import Vue from 'vue/dist/vue' /注册全局组件 // Vue.component('组件名称',{内容配置}) Vue.component('my-comp',{ //视图 template :template作为属性使用 必须vue.js (完整版的vue.js) 默认引入-运行时-vue.runtime.js template:'<div> <h2>我是一个全局组件</h2> <p>{{ msg }}</p></div>', //数据 data(){ return { msg:'hello vue全局组件' } }, //方法 methods:{ } })
-
全局组件--可以挂载创建好的局部组件 注册全局import MyBanner from './components/MyBanner.vue'// Vue.component('MyBanner',MyBanner)Vue.component(MyBanner.name,MyBanner)
-
vue 不同构建版本
-
vue.js 完整版 --编译器+ 运行时
-
vue.runtime.js 运行时
-
-
-
补充一个知识点
-
组件的视图模板组成
-
<template> 标签
-
template 属性使用
-
render() render函数渲染 -- react
-
-
优先级问题
<template> 标签 > render() > template (修改vue.js)
-
入门案例
代码如下:
父组件
<template> <div> <h2>这是我的第一个父组件</h2> <br> {{msg}} <hr> <Zi/> </div> </template> <script> import Zi from '@/components/vue-zi' export default { name: "vue-fu", components: { Zi }, data(){ return{ msg:'这是第一个父组件' } } } </script> <style scoped> </style>
子组件:
<template> <div> <h3> 这是一个子组件</h3> <br> {{name}}<br> </div> </template> <script> export default { name: "vue-zi", data(){ return{ name:"我是子组件" } } } </script> <style scoped> </style>
App.vue
<template> <div id="app"> <fu/> </div> </template> <script> import Fu from '@/components/vue-fu' export default { name: 'App', components: { Fu } } </script>
①创建父组件 vue
②创建子组件vue
③将子组件引入到父子间当中
④将父组件引人到 App.vue中使用
Prop传递数据
-
作用:实现组件之前数据传递- 父传子
案例一:父传子【数组方式】
基本传递
父组件Vue
<template> <div> <h2>这是我的第一个父组件</h2> <br> {{msg}} <hr> <Zi :msg="msg" :num="num" :username="username" :age="age" :sex="sex"></Zi> </div> </template> <script> import Zi from '@/components/vue-zi' export default { name: "vue-fu", components: { Zi }, data(){ return{ msg:'这是第一个父组件', num:20, username:'张小明', age:18, sex:'男' } } } </script> <style scoped> </style>
子组件Vue
<template> <div> <h3> 这是一个子组件</h3> <br> {{name}}<br> <hr> 哪个组件: {{msg}}<br> 姓名:{{username}}<br> 数字:{{num}}<br> 年龄:{{age}}<br> 性别:{{sex}}<br> </div> </template> <script> export default { name: "vue-zi", props:['msg','num','username','age','sex'], data(){ return{ name:"我是子组件" } } } </script> <style scoped> </style>
上述通过父传子传递的数组方式
子组件需要定义 props 来做接收。
记得父组件传递时需要单项绑定
父组件是可以修改传递的数据,子组件不能修改,只能是只读模式。
传递静态数据和动态数据,静态数据不需要绑定。
-
语法
-
父组件:<子组件 msg='hello' :info='' ></子组件>
-
子组件:数组接受:
props:['msg','info']
对象接受方式:
props:{ msg:数据类型 info:{ type:String, default:'默认值' }, ... 如下-prop验证 }
-
子组件使用父组件数据 直接当data里面的数据 使用{{ msg }}
-
注意:
-
prop传递数据时正向传递 父串子 数据时响应式的 父组件数据修改了 子组件同步更新
-
子组件不能直接修改prop传递的数据
-
4、prop验证
props: { // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证) propA: Number, // 多个可能的类型 propB: [String, Number], // 必填的字符串 propC: { type: String, required: true }, // 带有默认值的数字 propD: { type: Number, default: 100 }, // 带有默认值的对象 propE: { type: Object, // 对象或数组默认值必须从一个工厂函数获取 default: function () { return { message: 'hello' } } }, }
案例二:(父组件传递子组件)对象传递
props:{ texts:String,//传递的类型是String类型 msg:String, num:Number, username:[String,Number],//可以传递多种类型 age:Number, sex:String },
父组件:
<template> <div> <h4>父组件</h4> <hr> <!-- :arr="arr"--> <testC :username ="username" :age="age" :arr="arr" :user="user" ></testC> </div> </template> <script> import testC from '@/components/Vue-test-d' export default { name: "vue-test-c", components: { testC }, data(){ return{ username: "李小明", age:"十八", arr:["打篮球","踢足球","高尔夫"], user:{ name:'王二狗', sex:'男' } } } } </script> <style scoped> </style>
子组件:
<template> <div> <hr> <h5>这是子组件</h5> 姓名:{{username}}<br> 年龄:{{age}}<br> 性别:{{user.sex}}<br> 小名:{{user.name}}<br> 数组:{{arr}} </div> </template> <script> export default { name: "Vue-test-d", props:{ username:[String,Number], age:[String,Number,Object], arr:Array, user:Object } } </script> <style scoped> </style>
自定义事件 -- 子传父
-
作用:把子组件的数据传递给父组件 通过自定义事件
-
语法
-
子组件定义事件this.$emit('getData',this.msg)
-
父组件-调用子组件上面接受自定义事件<子组件 @自定义事件名='函数名'/>
methods:{
函数名(val){ this.xx = val; }
}
-
-
特殊的prop传递函数
-
prop传递的是一个函数名 <子组件 :fun='函数名' />
-
子组件接受props:['fun']
-
子组件调用 父组件传递的函数名fun this.fun() fun()
-
案例一:
父组件:
<template> <div> <h2>这是我的第一个父组件</h2> <br> {{msg}} <hr> <Zi texts="静态数据" :msg="msg" :num="num" :username="username" :age="age" :sex="sex" :getDataInfo="getDataInfo"></Zi> </div> </template> <script> import Zi from '@/components/vue-zi' export default { name: "vue-fu", components: { Zi }, data(){ return{ msg:'这是第一个父组件', num:20, username:'张小明', age:18, sex:'男' } }, methods:{ getDataInfo(val){ console.log(val); } } } </script> <style scoped> </style>
子组件:
<template> <div> <h3> 这是一个子组件</h3> <br> {{info}}<br> <button @click="setDataInfo">发送子组件</button> <hr> <!-- 哪个组件: {{msg}}<br> 姓名:{{username}}<br> 数字:{{num}}<br> 年龄:{{age}}<br> 性别:{{sex}}<br> 静态:{{texts}}--> </div> </template> <script> export default { name: "vue-zi", /* props:['texts','msg','num','username','age','sex'],*/ props:{ texts:String,//传递的类型是String类型 msg:String, num:Number, username:String, age:Number, sex:String, getDataInfo:Function }, data(){ return{ info:"我是子组件" } }, methods:{ setDataInfo(){ this.getDataInfo(this.info) } } } </script> <style scoped> </style>
注意:
子组件向父组件传递时,需要父组件定义方法,通过单项绑定发送给子组件,子组件需要接收后,将接收类型为Function,通过方法就可以传递了。
父组件:
<template> <div> <h3>父组件</h3> {{str}}<br> {{users.name}}<br> {{users.age}}<br> {{users.sex}}<br> {{arrs}} <!-- {{arrs}}--> <hr> <!-- {{this.username}}<br>--> <VueziTest :getDataInfo="getDataInfo"/> </div> </template> <script> import VueziTest from '@/components/test-vue-zi' export default { name: "test-vue-fu", data(){ return{ str:'', users:{}, arrs:[] } }, components: { VueziTest }, methods:{ getDataInfo(a,b,c){ this.str = a this.users = b /* this.users = a,*/ this.arrs = c console.log(a); console.log(b); console.log(c); } } } </script> <style scoped> </style>
子组件:
<template> <div> <h4> 子组件 </h4> {{title}}<br> {{user.name}}<br> <button @click="getDataInfos"> 发送数据</button> <hr> </div> </template> <script> export default { name: "test-vue-zi", data(){ return{ title :'学习Vue子传父', user:{ name:'张三', age:18, sex:'男' }, arr:['打篮球','踢足球'] } }, props:{ getDataInfo:Function }, methods:{ getDataInfos(){ this.getDataInfo(this.title,this.user,this.arr) } } } </script> <style scoped> </style>
插槽
-
说明:Vue 实现了一套内容分发的 API,定义时不知道具体要显示什么,只是留出来显示的位置,在组件调用时写具体内容,能展现在预留的位置上。
-
定义:使用 <slot> 标签预留位置
案例一:简单的插槽使用
父组件
<template> <div> <h2>这是父组件</h2> <SlotVue> 这是插槽slot </SlotVue> </div> </template> <script> import SlotVue from '@/components/slot-vue-zi' export default { name: "slot-vue-fu", components: { SlotVue } } </script> <style scoped> </style>
子组件
<template> <div> <h3> 我是子组件的定义</h3> <hr> <slot></slot> </div> </template> <script> export default { name: "slot-vue-zi" } </script> <style scoped> </style>
-
调用组件时写具体的要呈现的内容,要显示在<slot>标签中<组件> xxx </组件>
-
匿名插槽 (常用的)定义时: <slot name='default'></slot> / <slot></slot>
-
具名插槽 (常用的)
-
定义插槽的时候 有名字name属性<slot name='header'></slot> <slot name='footer'></slot>
2使用
<template v-slot:footer>
底部区域
</template>
-
注意:使用的时候 有名字的 在具名插槽里面显示 没有名字找匿名插槽
父组件
<template> <div> <h2>这是父组件</h2> <SlotVue> <template v-slot:footer> <h4> 这是具名插槽</h4> </template> </SlotVue> </div> </template> <script> import SlotVue from '@/components/slot-vue-zi' export default { name: "slot-vue-fu", components: { SlotVue } } </script> <style scoped> </style>
子组件
<template> <div> <h3> 我是子组件的定义</h3> <hr> <slot name="footer"></slot> </div> </template> <script> export default { name: "slot-vue-zi" } </script> <style scoped> </style>
-
6作用域插槽
父组件
<template> <div> <h2>这是父组件</h2> <SlotVue> <template v-slot:foot="foot"> <p>{{foot}}</p> </template> </SlotVue> </div> </template> <script> import SlotVue from '@/components/slot-vue-zi' export default { name: "slot-vue-fu", components: { SlotVue } } </script> <style scoped> </style>
子组件
<template> <div> <h3> 我是子组件的定义</h3> <hr> <slot name="foot" :msg="msg" str="学习Vue"></slot> </div> </template> <script> export default { name: "slot-vue-zi", data(){ return{ msg:'我是作用域插槽' } } } </script> <style scoped> </style>
-
作用: 让插槽内容能够访问子组件中才有的数据 (插槽提供数据)
-
语法:<slot name="footer" :msg="msg" :num='num'></slot>
-
使用插槽
<template v-slot:footer='data'> 底部区域</template>
注意:data一个对象 data={ msg:'',num:'',...}
-
具名插槽的缩写v-slot:header 可以被重写为 #header
-
后备内容有时为一个插槽设置具体的后备 (也就是默认的) 内容是很有用的,它只会在没有提供内容的时候被渲染。默认值
-
动态插槽名
-
作用:在调用插槽的时候 定义插槽的名字
-
语法:
-
<template v-slot:[varName]>我是具名插槽-{{varName}}</template>
-
data(){
return { varName:'header' }
}
-
-
总结所有vue指令
指令:v-指令='表达式' / v-xx='js环境'
-
v-text='表达式'插入字符串数据
<div v-text='msg'></div>
-
v-html='表达式'
-
插入HTML数据 解析html代码 识别标签
-
注意:不安全
-
-
v-show='表达式'
-
是否显示 true显示 false隐藏
-
控制css属性:diplay:block/none
-
-
v-if=''
-
是否显示 true显示 false隐藏
-
控制元素的创建和销毁
-
-
v-else
-
v-else-if=''
-
v-for=''
-
遍历数组 和对象
-
语法:
<div v-for='(item,index) in arr' :key='id'>{{ item }}</div><div v-for='(item,key,index) in obj' :key='id'>{{ item }}</div>
-
-
v-on:事件名='函数名'
-
绑定事件 简写: @事件名='函数名'
-
<div v-on:click='demo'>点击</div>
-
事件-修饰符
-
.stop
-
.prvent
-
键盘: .enter
-
-
-
v-bind:属性=''
-
动态绑定属性 简写: :属性=''
-
语法: <div v-bind:class='demo'>点击</div>
-
-
v-model=''
-
表单操作 获取数据 --- 双向数据绑定
-
语法: <input v-model='msg' />
-
实现原理:<input :value='val' @input='val=$event.target.value' />
-
-
v-slot=''
-
显示插槽内容
-
语法:
<template v-slot:插槽名字='数据'></template>
-
-
v-pre
-
不需要表达式 跳过这个元素和它的子元素的编译过程 -- 不编译vue语法 直接输出内容
-
<div v-pre>{{ msg }}</div>
-
-
v-cloak
-
这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。
-
[v-cloak] {display: none;}
<div v-cloak>{{ message }}</div>
-
-
v-once
-
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。
-
可以用于优化更新性能
-
语法: <div v-once>一定不修改:{{ msg }}</div>
-
异步组件
什么时间用什么时间加载组件。
Objs:()=>import('@/components/vue-object'),
Vue的生命周期 参考官网。
生命周期函数:
-
beforeCreate new vue实例后 创建之前 -- 获取到data methods 和数据等。
-
created *** 创建之后
-
beforeMount 挂载之前
-
mounted *** 挂载完毕 -- 初次获取DOM元素的地方
-
beforeUpdate 更新之前 数据更新了 视图时旧的
-
updated *** 更新之后 数据和视图 同步
-
beforeDestory 销毁之前 什么都可以用
-
destory 销毁之后 清空数据 或者时计时器等
生命周期测试代码
<template> <div> <h2>生命周期函数</h2> <div id="main">id</div> <p>msg:{{ msg }}</p> <button @click="msg = '我是新修改的msg'">修改msg</button> <!-- <ul> <li v-for="item in banner" :key="item.title"> <h3>{{ item.title }}</h3> <p>{{ item.content }}</p> </li> </ul> --> </div> </template> <script> export default { name: "life", data() { return { msg: "hello", banner: [], }; }, methods: { demo() {}, }, //生命周期函数 和data 同级 //1.创建之前 beforeCreate() { console.group("beforeCreate--创建之前-获取不到data-methods"); console.log('this',this) console.log("el-dom", this.$el); console.log("data", this.$data); console.log("msg", this.msg); }, //2. 创建之后 /*created() { console.group("created--创建之后-首次获取data-methods"); console.log('this',this) console.log("el-dom", this.$el); console.log("data", this.$data); console.log("msg", this.msg); //最早:网络请求 --- juquery },*/ //3. beforeMount /* beforeMount() { console.group("beforeMount--挂载之前---获取不到dom元素"); console.log("el-dom", this.$el); console.log("data", this.$data); console.log("msg", this.msg); console.log("dom", document.getElementById("main")); },*/ //4.mounted /* mounted() { console.group("mounted--挂载之后---获取dom元素"); console.log("el-dom", this.$el); console.log("data", this.$data); console.log("msg", this.msg); console.log("dom", document.getElementById("main")); },*/ //5. beforeUpdate /* beforeUpdate() { // debugger; console.group("beforeUpdate--更新之前---视图不更新"); console.log("data", this.$data); console.log("msg", this.msg); // debugger; },*/ //6.updated /* updated() { console.group("updated--更新之后---视图更新完毕"); console.log("data", this.$data); console.log("msg", this.msg); },*/ //7. beforeDestory 销毁之前 什么都可以用 /*beforeDestroy() { console.group("beforeDestory 销毁之前 什么都可以用"); console.log("data", this.$data); console.log("msg", this.msg); },*/ //8.destoryed /* destroyed() { console.group("destoryed 销毁之后 什么都可以用--数据初始化-清空计时器"); console.log("data", this.$data); console.log("msg", this.msg); },*/ } </script> <style scoped> </style>
路由
Vue Router 是 Vue.js (opens new window)官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
-
嵌套的路由/视图表
-
模块化的、基于组件的路由配置
-
路由参数、查询、通配符
-
基于 Vue.js 过渡系统的视图过渡效果
-
细粒度的导航控制
-
带有自动激活的 CSS class 的链接
-
HTML5 历史模式或 hash 模式,在 IE9 中自动降级
-
自定义的滚动条行为
-
介绍vue组件中实现页面的跳转 配置路由--通过路由实现页面的跳转的
-
安装路由
-
安装命令:npm install vue-router -S
-
引入路由插件-main.jsimport Vue from 'vue'import VueRouter from 'vue-router'Vue.use(VueRouter)
-
定义 (路由) 组件 import Home from './Home.vue'import About from './About.vue'
-
定义路由 -- 页面走向const routes = [
{ path: '/', //path:地址栏的路径 /+字母 component: Home //跳转这个路径显示的组件:页面 }, { path: '/news', component: News },
]访问首页:http://localhost:8080/#/ --> Home访问新闻:http://localhost:8080/#/news --> News
-
创建router实例const router = new VueRouter({
routes:routes
})
-
挂载路径new Vue({
router:router,
})
-
显示路由出口<router-view></router-view>
-
路由导航<router-link to='/path'>首页</router-link><router-link to='/'>首页</router-link><router-link to='/news'>新闻</router-link>属性: to='/+路径' 路径-路由里面配置的path路径 exact 精准匹配
-
-
安装路由 vue-cli
-
安装项目的时候选择 router
-
vue create vue-router
-
动态路由匹配
-
介绍路由传递参数 如何给路由传递参数 如何接受参数
-
语法:const router = new VueRouter({
routes: [ // 动态路径参数 以冒号开头 { path: '/user/:id', component: User } ]
})
-
获取动态路由传递的参数
-
this.$route.xxx
-
-
$route
-
fullPath 路由路径的全地址
-
matched 数组格式 包含当前的路由路径 以及 父组件路由路径
-
name 路由名称
-
params {} 路由动态参数 定义路由:/user/:uname params={uname:xx}
-
path 路由路径走向
-
query 地址栏参数 xx?aa=123
-
嵌套路由
-
介绍路由的嵌套 当前的路由下面包含一级或者多级路由导航
-
写法:const router = new VueRouter({
routes: [ { path:'/zhinan', component:Zhinan, children:[//二级路由 { path:'anzhuang',//访问地址: /zhinan/anzhuang -- 推荐写法 component:, children:[//三级路由 ] }, { path:'/base',//访问地址: /base component:, } ] } ]
})
编程式的导航
-
介绍除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现 说明:跳转路由的两种方式
-
标签跳转路由 <router-link to=''></router-link>
-
编程式-js跳转路由
-
router.push()
-
router.replace()
-
router.go(n)
-
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
-
在浏览器记录中前进一步,等同于 history.forward()router.go(1)
后退一步记录,等同于 history.back() router.go(-1)
前进 3 步记录 router.go(3)
-
-
-
-
访问注意:在 Vue 实例内部,你可以通过 访问路由实例。因此你可以调用router.push
命名路由
-
介绍通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候
-
功能
-
跳转路由 - 编程式跳转this.$router.push({ name: 'User', params: { uname: 123,id:xx } })
-
router-link 的 to 属性传一个对象<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
-
重定向和别名
-
重定向也是通过 routes 配置来完成,下面例子是从 /a 重定向到 /bconst router = new VueRouter({
routes: [ { path: '/a', redirect: '/b' } ]
})
-
别名
-
含义:小名 其他名称 都是一个人
-
语法:const router = new VueRouter({
routes: [ { path: '/a', component: A, alias: '/b' } ]
})
-
第一步:安装路由:
npm i vue-router@3.x --S
第二步 创建路由目录:
在src目录下创建一个目录为:router 同时在router 目录中创建index.js文件。
同时在src目录下创建pages 目录存放页面。
index.js
/(1)先导入Vue import Vue from 'vue' import VueRouter from "vue-router" //(2)加载到Vue对象中 Vue.use(VueRouter) import Home from "@/pages/Home"; //(3)配置路由走向 const routers = [ { path:'/', component:Home }, { path:'/new', component: () => import( '../pages/New.vue') } ] //(4)挂载路由 const router = new VueRouter({ routers }) //(5)导出路由 export default router
main.js
//(6)导出路由 import router from "@/router/index"; new Vue({ render: h => h(App), //(7)挂载路由到Vue中 router }).$mount('#app')
App.vue
<router-link to="/">首页</router-link>| <router-link to="/new">新闻</router-link> <router-view></router-view>
子路由 配置写到children下面。
如下:
children: [{ }}
案例一:(认识路由:)(课上操作新建项目)
element UI讲解
element UI 一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库。
安装:
npm i element-ui -S
需要在main.js中引入element-ui
有两种引入方式:
一全局引入
import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI);
二按需加载:
Vue.component(Button.name, Button); Vue.component(Select.name, Select);
全局配置的时候里面可以配置样式的大小如下:
Vue.use(Element, { size: 'small', zIndex: 3000 });
Element也是24 分栏布局。
下面是常用的布局。
开发当中只需要将它的UI组件引入到项目当中就可以了。