- 开发人员大部分在用Vue开发
- Vue学习曲线相比其他框架简单很多
- 目前前端 必备 技能
- 传统方式已经不能适应目前越来越 复杂 的开发需求
- 用vue的开发方式会简单、高效
- 三大框架(vue、react、angular)
- 1. 不用操作DOM
- 2. 单页面应用web项目(SinglePageApplication 项目,例如https://worktile.com/)简称:SPA
- 3. 传统网站开发 一般来说 需求不大
- 4. 当下各种新框架都采用了类似Vue或者类似React的语法去作为主语法, 微信小程序/MpVue.....
- 结论: 掌握Vue的开发语法 相当于掌握了新的开发模式,可以适应目前绝大多数的技术环境
- 1. 数据驱动视图 可以让我们只关注数据
- 2. MVVM 双向绑定
- 3. 通过 指令 增强了html功能
- 4. 组件化 复用代码
- 5. 开发者一般只需要关注数据
- Vue官方文档
- Vue开源项目汇总
- Vue.js中文社区
- 所有关于Vue的问题都可以通过查阅文档解决
1. 直接下载源码然后通过路径引入
2. 在线cdn引入的方式
3. 采用 npm 安装的方式
// 现状: 都会采用npm的方式来进行正式项目开发
npm install vue
注意: Vue.js 不支持 IE8 及其以下版本
步骤 :
- 1. body中,设置Vue管理的视图
- 2. 引入vue.js
- 3. 实例化Vue对象new Vue();
- 4. 设置Vue实例的选项:如el、data...
- new Vue({选项:值});
- 5. 在 中通过{{ }}使用data中的数据
// 1.我是Vue所管理的视图div #app
// 5.在视图里使用Vue实例中data里面的list数据
< p > {
{
list
}
} < /p>
// 2.引入vue.js
- 作用:当前Vue实例所管理的html视图
- 值:通常是id选择器(或者是一个dom对象)
- 注意!!!!不要让el所管理的视图是html或者body!!!!
路径:
new Vue({ // el: '#app' , id选择器 // el: '.app', class选择器 el: document.getElementById("#app") // dom对象 })
任务:
- 1. 尝试用 id选择器 设置el 页面显示hello world
- 2. 尝试用class选择器 设置el 页面显示hello world
- 3. 尝试用dom对象 设置el 页面显示hello world
- 4. 尝试设置html 或者body为el 查看效果
掌握data基本用法
Vue 实例的data(数据对象),是响应式数据(数据驱动视图)
- 1. data中的值{数据名字:数据的初始值}
- 2. data中的数据msg/count 可以在视图中通过{{msg/count}}访问数据
- 3. data中的数据也可以通过实例访问 vm.msg或者vm.$data.msg
- 4. data中的数据特点:响应式的数据->data中的数据一旦发生变化->视图中使用该数据的位置就会发生变化
路径
let vm = new Vue({
el: "#app",
data: {
msg: 'abc',
count: 100
list: [1, 2, 3]
}
})
vm.msg = 200
console.log(vm)
console.log(vm.msg)
console.log(vm.$data.msg)
任务
1. 将数据对象中count初始值设置为100
2. 通过vm.属性的方式打印 以上三个属性
3. 通过 {{ 变量名 }} 的方式 将以上三个属性显示在页面上
4. 通过vm.属性 = 赋值的方式,改变 count 为300、msg为"铁蛋儿最帅"、数组为 [1,2,3,4]
掌握实例选项methods中方法的使用及注意事项
- methods其值为一个对象
- 可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。
- 方法中的 this 自动绑定为 Vue 实例。
- methods中所有的方法 同样也被代理到了 Vue实例对象上,都可通过this访问
- 注意,不应该使用箭头函数来定义 method 函数。理由是箭头函数绑定了父级作用域的上下文,所以this 将不会按照期望指向 Vue 实例
let vm = new Vue({
el: "#app",
data: {
name: "Hello world",
name2: "Hello world2"
},
methods: {
// 常规函数写法
fn1: function () {
console.log(this.name)
this.fn2()
},
// es6 函数简写法
fn2() {
console.log(this.name2)
}
}
})
任务:
1. 实例化一个Vue实例,
2. 定义两个属性 name1 name2 初始值分别为 Hello world Hello world2
3. 定义两个方法 fn1 fn2 两个方法中分别输出 name1 和 name2的值
路径: 参照代码示例
- 理解和使用插值表达式
- 作用:会将绑定的数据实时的显示出来
- 形式: 通过 {{ 插值表达式 }} 包裹的形式
- 用法:{{js表达式、三元运算符、方法调用等}}
// 错误写法
{{ var a = 1 }}
{{ if (ok) { return message } }}
// 正确写法
{{ 1 + 2 + 3 }}
{{ 1 > 2 }}
{{ name + ':消息' }}
{{ count === 1 }}
{{ count === 1 ? "成立" : "不成立" }}
{{ fn() }}
任务
1. 初始化一个Vue实例
2. 在data中定义 name: "张三" count: 2 , list:'123'
3. 要求根据data中的数据用插值表达式输出 张三, 2, 321,
- 指令 (Directives) 是带有 v- 前缀的特殊特性。
- 指令特性的值预期是单个 JavaScript 表达式( v-for 是例外情况,稍后我们再讨论)。
- 指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
- 指令位置: 起始标签
代码示例:
内容
任务 :
1. 初始化一个Vue实例
2. 定义一个data属性 name: 我是内容
3. 使用v-text指令将data内容显示在p标签上
- 很像innerText和innerHTML
- v-text:更新标签中的内容
- v-text和插值表达式的区别
- v-text 更新 整个 标签中的内容
- 插值表达式: 更新标签中局部的内容
- v-html:更新标签中的内容/标签
- 可以渲染内容中的html标签
- 注意:尽量避免使用,容易造成危险 (XSS跨站脚本攻击)
< div id = "app" >
< p > {
{
str
}
} < /p>
< p v - text = "str" > 我是p标签中的内容 < /p>
我是p标签中的内容
< p v - html = "str" > < /p>
我是p标签中的内容
< /div>
任务
1. 初始化一个vue实例
2. 定义一个 数据对象 name: 张三
3. 分别使用v-text和插值表达式将张三显示在p标签上
4. 定义一个数据对象 nameHtml: 内容,使用v-html将内容显示在p标签上,并且内容为红色
- 使用: v-if 和 v-show 后面跟着表达式的值是布尔值 ,布尔值来决定该元素显示隐藏
- 注意 : v-if 是直接决定元素 的 添加 或者删除 而 v-show 只是根据样式来决定 显示隐藏
- v-if 有更高的切换开销
- v-show 有更高的初始渲染开销。
- 如果需要非常频繁地切换,则使用 v-show 较好.
- 如果在运行时条件很少改变,则使用 v-if 较好.
我是小白龙
我是铁蛋儿
任务 :
1. 定义一个Vue实例
2. 定义一个布尔型变量isShow
3. 分别使用v-if 和 v-show来条件渲染 P标签内容
- 使用:
- 第一种:v-on:事件名="方法名"
- 第二种:@事件名="方法名"的方式
// v-on:xx事件名='当触发xx事件时执行的语句' // v-on的简写方法
- 修饰符
- 使用:@事件名.修饰符="方法名"
- .once - 只触发一次回调
- .prevent - 调用 event.preventDefault() 阻止默认事件
// v-on修饰符 如 once: 只执行一次
// v-on修饰符 如 prevent: 阻止默认事件
事件对象(扩展)
- 第一种:方法名中采用$event的方式传形参
- 第二种:直接写事件名 默认第一个参数为event事件参数
任务 :
- 1. 初始化一个Vue实例,
- 2. 添加一个button按钮
- 定义data中 name 为hello world
- 注册button点击事件 获取当前data对象中的name值 输出
- 3. 添加一个 input文本框
- 注册input值改变事件 值改变时获取 文本框内容(扩展)
// 第一种用法:
< ul >
< li v -for = "item in items" >
{{item.name}}
< /li>
// data中的数组
data: {
items: [
{
name: '大娃'
},
{
name: '二娃'
}
]
}
// 第二种用法: v-for 还支持一个可选的第二个参数,即当前项的索引
-
{{ index }} { {item.name}}
- 注意 : v-for写的位置 应该是重复的标签上 不是其父级元素上 需要注意
- 任务 :
- 1. 初始化一个Vue实例
- 2. 定义data对象中list:['北京','上海','天津']
- 3. 将list中的内容 v-for循环在li标签上显示
- 路径 参照代码示例
第一种用法:
// items 为对象 item为当前遍历属性对象的值
v-for="item in items"
第二种用法:
//item为当前遍历属性对象的值 key为当前属性名 index为当前索引的值
v-for="(item, key, index) in items"
任务 :
1. 初始化一个Vue实例
2. 定义data对象中 person: { name: '张三', sex:'男',age: 18 }
3. 将person中的内容 v-for循环在li标签上显示
路径 参照代码示例
场景: 列表数据变动会导致 视图列表重新更新 为了提升性能 方便更新 需要提供一个属性 key
// 使用v-for时 建议给每个元素设置一个key属性 (必须加上)
// key属性的值 要求是每个元素的唯一值 (唯一索引值)
// 好处:vue渲染页面标签 速度快
// 数组
{{v}}
// 对象
{{v}}-{{k}}
任务:
1. 初始化一个Vue实例
2. 定义data对象中list:['北京','上海','天津']
3. 将list中的内容 v-for循环在li标签上显示
4. 给每个li标签赋值key
通过分析页面需求,提取案例功能点
功能点:
1. 添加商品
2. 删除商品
3. 搜索商品
4. 列表循环
5. 数据不存在 显示不存在数据
6. 时间格式
代码:https://gitee.com/shujuanlanyan/vue-foundation/blob/master/vue%E5%9F%BA%E7%A1%801/%E5%8F%82%E8%80%83%E6%95%88%E6%9E%9C.html
完成表格案例的列表渲染
路径:
1. 静态页面准备
2. 实例化一个Vue
3. 定义表格数据
4. 采用v-for 循环将静态内容切换为动态内容
5. 采用v-if控制提示消息
代码:https://gitee.com/shujuanlanyan/vue-foundation/blob/master/vue%E5%9F%BA%E7%A1%801/%E9%9D%99%E6%80%81%E9%A1%B5%E9%9D%A2.html
- 作用: 绑定标签上的任何属性
- 场景: 当标签上的属性是变量/动态/需要改变的
- 用法:
// ID为数据对象中的变量值 // 简写
- 用法: 绑定class对象语法 :class="{ class名称: 布尔值}"
内容
// isBn为 data选项中的属性
- 注意 : 绑定class和原生class会进行合并(但是不会合并重复的)
- 绑定class数组语法 :class="[a,b]"
内容
data:{ a:'obox', b:'left' }
- a、b为data属性的key
- data中key对应的value 为class名字
- 语法 :style="{css属性名:属性值}"
- 注意 css属性名 例如 font-size要写成 fontSize 以此类推 原有的style会覆盖
< p: style = "{color:a,fontSize:b}" > < /p> / / a、 b为 data属性的 key data: { a: 'red', b: '30px' },
// 语法: < div: style = "[a,b]" > < /div> / / a, b为 data的属性 data: { a: { color: "red" }, b: { fontSize: "30px" } }
注意 对象可以是多个属性的 集合 同样里面的css属性需要遵从小驼峰命名的规则
- 作用: 表单元素的绑定
- 特点: 双向数据绑定
- 数据发生变化可以更新到界面
- 通过界面可以更改数据
- v-model 绑定表单元素,会忽略所有表单元素的 value 、 checked 、 selected 特性的初始值
- 表单元素会将 Vue 实例的data中的数据作为数据来源,所以应该在 data 选项中声明初始值。
// 表单中设置value值没用 v-model会忽略 < input type = "text" v-model = "msg" value = "zhang" > < p > { { msg } } < /p> / / 在data中设置 msg data: { msg: 'zhangsan' }
分析
- 表单元素绑定的数据改变 => data数据发生改变=> 页面数据变化
{{msg}}
任务 :
1. 实例化一个Vue实例
2. input 绑定 属性 nameInput,实现input同步
3. textarea 绑定 属性 nameTextArea 实现textarea同步
4. checkbox 绑定一个属性 nameCheckbox 实现 checkbox同步
5. 多个 checkbox绑定同一个属性 nameCheckboxs 实现 checkbox同步 北京 上海 天津
6. radio 绑定属性 nameRadio 实现同步 男 女
7. select 绑定属性 nameSelect 实现同步 北京 上海 天津
路径: https://cn.vuejs.org/v2/guide/forms.html
场景: 解决页面初次渲染时 页面模板闪屏现象
1. 写入v-cloak指令
2. 在style里面加给v-cloak加上display: none;
注意: 避免多次写入标签 可以一次性 将v-cloak引用在实例视图上
{{msg}}
作用: 指令所在元素只渲染一次
{{msg}}
- 场景: 格式化data数据(日期格式/货币格式/大小写等)
- 分类: 本地(局部)和全局 全局是所有实例均可使用
- 本地:https://gitee.com/shujuanlanyan/vue-foundation/blob/master/vue%E5%9F%BA%E7%A1%802/09.%E5%B1%80%E9%83%A8%E8%BF%87%E6%BB%A4%E5%99%A8.html
// 组件的选项中定义本地的过滤器 filters: { 过滤器名字:function (value) { return .... } }
- 全局:https://gitee.com/shujuanlanyan/vue-foundation/blob/master/vue%E5%9F%BA%E7%A1%802/08.%E5%85%A8%E5%B1%80%E8%BF%87%E6%BB%A4%E5%99%A8.html
// 如何注册一个全局过滤器 Vue.filter("过滤器名字", function(value) { return ...... });
- 使用:
// 过滤器应该被添加在尾部 每个过滤器用管道符分隔 // 第一种用法在双花括号中 {{ 数据 | 过滤器名字 }} // 第二种用法在 v-bind 中
任务:
1. 看过滤器API的用法https://cn.vuejs.org/v2/guide/filters.html>
1. 在创建 Vue 实例 之前 定义全局过滤器Vue.filter()
2. 在实例的filter选项中定义局部过滤器
3. 在视图中通过{{数据 | 过滤器名字}}或者v-bind使用过滤器
// 如何注册一个全局过滤器
Vue.filter("过滤器名字", function(value) {
return value.charAt(0).toUpperCase() + value.substr(1);
});
// 如果注册一个局部过滤器
filters: {
过滤器名字:function (value) {
return value.charAt(0).toUpperCase() + value.substr(1);
}
}
任务 : 注册一个全局或者局部过滤器,实现 abc 转成 Abc的功能
过滤器可以传递参数,接收的第一个参数永远是前面传递过来的过滤值
过滤器也可以多个串行起来并排使用,
// 多个过滤器用 | 分割
{{count|a('元')|b}}
// 定义过滤器 filters:{ // 第一个参数永远是前面传递过来的过滤值 a:function(val,y){ // val 是count值 // y 是‘元’ } }
- 任务 :实现一个过滤器,假如是数字100过滤完出来是100元人民币
实现:https://gitee.com/shujuanlanyan/vue-foundation/blob/master/vue%E5%9F%BA%E7%A1%802/10.%E8%BF%87%E6%BB%A4%E5%99%A8%E9%AB%98%E7%BA%A7%E7%94%A8%E6%B3%95.html
路径 : 格式化需要借助第三方插件
1 . 引入第三方格式化日期插件 moment.js http://momentjs.cn/
2 . 定义格式化日期过滤器
3. 实现其格式化功能
4 . 使用过滤器
// 全局过滤器代码 Vue.filter("fmtDate", function (v) { return moment(v).format('YYYY-MM-DD h:mm:ss a') })
实现:https://gitee.com/shujuanlanyan/vue-foundation/blob/master/vue%E5%9F%BA%E7%A1%802/11.%E8%BF%87%E6%BB%A4%E5%99%A8%E5%AE%9E%E7%8E%B0%E6%97%A5%E6%9C%9F%E6%A0%BC%E5%BC%8F%E5%8C%96.html
使用: 给元素定义ref属性, 然后通过$refs.名称 来获取dom对象
// 定义ref
// 获取DOM的value值 methods: { getVal() { //获取dom console.log(this.$refs.txt) } }
任务 通过ref功能,点击按钮时获取input的value值
- 使用场景:需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令
- 分类:全局和局部
- 全局自定义指令:
1. 在创建 Vue 实例之前定义全局自定义指令Vue.directive(参数1,参数2)
- 第一参数是指令名称
- 第二参数是一个对象
- 对象中要实现inserted方法
- inserted方法中的参数为当前指令 所在元素的DOM对象
// 1.注册一个自定义指令 Vue.directive('指令名称', { inserted(参数) { //参数为使用指令的DOM //操作 } }) // 2.使用自定义指令 < input type = "text" v - 指令名称 >
// 示例(全局自动聚焦的自定义指令) Vue.directive("focus", { inserted(dom) { dom.focus(); } }); // 使用自定义指令 < input type = "text" v - focus >
任务 实现一个可以自动聚焦input的自定义指令v-focus
//局部指令在vue实例内部定义 directives: { "focus": { inserted(dom) { dom.focus(); } } } // 调用
任务 实现一个可以自动聚焦input的局部自定义指令v-focus
目标: 根据所学自定义指定 实现表格案例 自动获取焦点功能
https://gitee.com/shujuanlanyan/vue-foundation/blob/master/vue%E5%9F%BA%E7%A1%802/13.%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8C%87%E4%BB%A4.html
- 场景:当表达式过于复杂的情况下 可以采用计算属性 对于任何复杂逻辑都可以采用计算属性
- 参考: https://cn.vuejs.org/v2/guide/computed.html#基础例子
使用: 在Vue实例选项中 定义 computed:{ 计算属性名: 带返回值 的函数 }
示例: 通过计算属性实现字符串的翻转
``js data: { message: 'hello' }, computed: { reverseMessage: function () { // this指向 vm 实例 return
this.message.split('').reverse().join('') } } // computed里的函数直接用 不加() 但是必须得return
{{ message }}
{{ reversedMessage }}
**计算属性 和 methods方法的区别:**
- 1. 计算属性不需要调用形式的写法 而methods方法必须采用 方法() 调用的形式
- 2. 计算属性依赖data中的数据变化,如果data并没有发生变化,则计算属性则会取缓存的结果,
- 3. methods不论data变化与否 只要调用 都会重新计算
**`注意:`**当数据对象中 message发生变化时 计算属性也会重新计算计算=> 改变页面视图
效果 搜索框内容变化=> 列表内容变化
使用计算属性实现品牌搜索
1.定义品牌搜索的内容
2.定义计算属性
3.实现计算属性的筛选功能(筛选列表)
4.计算属性替换原有的列表数据
computed: { newList() { return this.list.filter((v) => { return v.name.startsWith(this.searchVal) }) } }
原理 : Vue.js中发送网络请求本质还是ajax,我们可以使用插件方便操作。
- 1. vue-resource: Vue.js的插件,已经不维护,不推荐使用
- 2. axios : 不是vue的插件 ,可以在任何地方使用,推荐
说明 : 既可以在 浏览器端 又可以在 node.js 中使用的发送http请求的库,支持Promise ,不支持jsonp
如果遇到jsonp请求, 可以使用插件 jsonp 实现
用法:
1.下载axios.js
2,在文件中引入
- //下载json-server
- npm i json-server -g
- //启动服务 json-server 文件名
- json-server db.json
- //postman 工具分别可以对这个接口进行增删改查
// 基本用法
axios.get(url).then((res) => {
// 请求成功 会来到这 res响应体
}).catch((err) => {
// 请求失败 会来到这 处理err对象
})
// 获取
axios.get('http://localhost:3000/brands').then().catch()
// 删除
axios.delete('http://localhost:3000/brands/1').then().catch()
// 添加
axios.post('http://localhost:3000/brands', {name: '小米', date: new Date()}).then().catch()
// 修改
axios.put('http://localhost:3000/brands/1', {name: '小米', date: new
Date()}).then().catch()
// get模糊搜索
axios.get("http://localhost:3000/brands?name_like=" + "aaa").then().catch()
目标: 将表格案例中列表数据实现用axios请求
路径: 使用axios请求列表
1. 引入axios
2. 在mounted(相当于window.onload)函数中 发送请求获取数据
3. 获取的数据赋值给list列表
mounted() { axios.get('http://localhost:3000/brands').then((res) => { this.list = res.data }).catch((err) => { console.log(err) }) },
注意 :mounted函数相当于window.onload,后面会详细的讲到
路径: 使用axios删除商品
1.删除方法中传入ID
2.删除方法中调用删除接口
3.删除完成后重新调用获取数据
代码:
deleItem(id) {
if (confirm('是否删除')) {
axios.delete('http://localhost:3000/brands/' + id)
.then((res) => {
this.getData()
}).catch((err) => {
console.log(err)
})
}
}
}
路径: 使用axios添加商品
1. 添加方法中调用新增接口
2. 添加成功后重新拉取数据
3. 清空输入框
addItem() {
axios.post('http://localhost:3000/brands', {
name: this.name,
date: new Date()
}).then((res) => {
const {
status
} = res
if (status == 201) {
// 成功以后重新刷列表
this.getData()// 重新拉取数据
this.name = ""; // 清空文本框
}
}).catch((err) => {
console.log(err)
})
}
目标: 通过分析得出 计算属性中不能进行搜索功能的结论
计算属性=> 异步操作搜索=>返回结果 XXXXX 走不通
结论: 搜索功能不能采用 计算属性 进行解决
注意: 计算属性中一定是 同步操作 ,如果有 异步 操作,则该业务逻辑就会失败
新知识: 当需要根据数据变化 进行相应业务操作,且该操作是 异步操作 时,计算属性不能再使用,可以使用侦听属性watch
特性: 监听data数据变化时 自动触发函数
计算属性和watch区别:
- 计算属性 必须要有返回值 所以说不能写异步请求 因为有人用它的返回值(插值表达式)
- watch选项中可以写很多逻辑 不需要返回值 因为没有人用它的返回值
data: { msg: 'hello' }, watch: { // data中的属性msg发生改变时 自动触发该函数 msg(newV, oldV) { console.log(newV, oldV) } }
1. 监听搜索内容
2. 在监听函数中 发送axios请求实现模糊搜索
3. 把返回值赋值给list列表
// 实例代码 watch: { searchval(newV, oldV) { axios.get("http://localhost:3000/brands?name_like=" + newV) .then((res) = > { this.list = res.data }). catch (err = > { console.log(err) }) } }
场景: 重复的页面结构,数据,逻辑 都可以抽提成一个组件
特点 简单 高效 不重复
组件和实例相似之处: data/methods/computed/watch 等一应俱全
注意:
- data和Vue实例的区别为
- 组件中data为一个函数且需要返回一个对象
- 组件没有el选项
- template 代表其 页面结构 (有且只要一个根元素)
每个组件都是 独立 的 运行作用域、数据、逻辑没有任何关联
全局和局部: 注册方式不同 应用范围不同
注意: 注意命名规范
路径: 实现一个全局组件
- 1. 定义一个全局组件
- 2. 写入组件选项
- 3. 使用组件
// 注册组件名称 推荐 小写字母 加横向的结构 Vue.component("content-a", { template: ` < div > { { count } } < /div>`, data() { return { count: 1 }; } });
// 注意 data中必须为一个返回对象的函数 // template必须有且只有一个根元素
任务 实现一个全局组件 完成 加减步进器
https://gitee.com/shujuanlanyan/vue-foundation/blob/master/vue%E5%9F%BA%E7%A1%803/09.%E5%8A%A0%E5%87%8F%E7%BB%84%E4%BB%B6.html
局部组件的实现
1.在实例选项compoents中定义局部组件名字
2.在组件名字相对应的对象中定义选项(template、data()、.....)
3.在实例视图中使用组件
// 局部组件 // 1.实例选项compoents中定义局部组件名字 components: { // 2.在组件名字相对应的对象中定义选项(template、data()、.....) "z-j": { template: '
我是局部组件{{msg}}
', data() { return { msg: '我是小白龙' } } } } }) // 3.在实例视图中使用组件
- 1. 全局组件 嵌套 全局组件
- 2. 局部组件 嵌套 全局组件
注意: 组件嵌套和全局及局部组件没关系
组件嵌套 => 父子组件 => 父组件传递数据给子组件使用 => 组件之间的传值 => 也叫组件之间的通信
组件之间的通信根据关系的可以分为:
1. 父子组件通信
- 父组件到子组件
- 子组件到父组件
2. 兄弟组件通信
父子组件的传值有多种方法, 兄弟组件的通信也有自己的写法
1. 子组件的 props 属性值是一个数组
2. 数组中的值 绑定为子组件上的属性 用来接受父组件的传值
3. 在子组件的template中就可以使用 绑定的属性(msg)拿到父组件传递的值
- 模块:侧重于功能或者数据的封装
- 组件:包含了 template、style 和 script,而它的 script 可以由各种模块组成
- 传统模式 每个页面及其内容都需要从服务器一次次请求 如果网络差, 体验则会感觉很慢
- SPA模式, 第一次 加载 会将所有的资源都请求到页面 模块之间切换 不会再请求服务器
SPA优点:
- 1. 用户体验好,因为前端操作几乎感受不到网络的延迟
- 2. 完全组件化开发 ,由于只有一个页面,所以原来属于一个个页面的工作被归类为一个个 组件 .
SPA缺点:
- 1. 首屏 加载慢(可以只加载所需部分)
- 2. 不利于 SEO ( 服务端渲染 可以解决)
- 3. 开发难度高 (框架)
原理:
- 可以通过页面地址的锚链接来实现spa
- hash(锚链接)位于链接地址 # 之后
- hash值的改变 不会触发 页面刷新
- hash值是url地址的一部分,会存储在页面地址上 我们可以获取到
- 可以通过 事件监听 hash值得改变
- 拿到了hash值,就可以根据不同的hash值进行不同的 内容切换
- 通过上一个小节内容可以得出 采用 hash值改变 的特性来进行前端路由切换
路径 :
- 1. 实现导航结构('#/aaa')
- 2. onhashchange事件监听hash值的改变
- 3. 获取hash值 根据值的不同 改变视图内容
https://gitee.com/shujuanlanyan/vue-foundation/blob/master/vue%E5%9F%BA%E7%A1%804/04-js%E5%AE%9E%E7%8E%B0%E8%B7%AF%E7%94%B1.html
Vue-Router 是 Vue.js 官方的路由管理器。
它和 Vue.js 的核心深度集成,让构建单页面应用变得简单
实现根据不同的请求地址 而 显示不同的内容
如果要使用 vue开发项目,前端路由功能 必须使用 vue-router来实现
用法:
- 1. CDN
- 2. 本地文件
- 3. npm
注意: 本地文件引入vue-router ,一定要先引入vue.js,再引入vue-router
1. 导入vue和vue-router
2. 设置HTML中的内容
3. 实例化路由对象,配置路由规则
4. 创建路由对应的组件
5. 把router实例挂载到vue实例上
2.设置HTML中的内容
用户管理 首页展示 // 3.配置路由规则 var router = new VueRouter({ routes: [ { path: '/users', component: Users } { path: '/home', component: Home } ] });
// 4.创建组件 let Home = { template: '
这是Home内容' }; let Users = { template: '这是用户管理内容' };// 5.把router实例挂载到vue实例上 var vm = new Vue({ el: '#app', router });
- to 有多种赋值方式
(注意:name值是字符串) (注意:必须得加上/ 不然容易错乱) (注意获取参数route 不要写成router)
场景: 当希望某个页面被强制中转时 可采用redirect 进行路由重定向设置
path: "/bj",
redirect: "/sh", // 强制跳转上海
component: {
template: `体育`
}
场景: 点击的时候路由实现跳转
methods: {
goPage() {
// 跳转到新闻页面
this.$router.push({
path: "/news"
});
}}
- 当前路由在导航中是拥有激活class样式的
审查导航元素,可以发现 激活样式
北京
设置激活class样式即可
如果存在 组件嵌套 ,就需要提供多个视图容器
同时,router-link和router-view 都可以添加类名、设定样式
路径:
1. 在原有的一级导航的template里面 配置 二级导航的router-link和router-view
2. 在相对应的一级导航路由配置选项children里面 配置 二级导航的路由和模板
path: '/music', component: Music, //子路由配置 在children选项 children: [{ path: 'lx', component: Lx },...]
任务
1. 实现一个嵌套路由
2. 第一级路由为 首页 、音乐、体育
3. 音乐下 二级路由为古典、 流行、爵士
基本用法就是给我们需要动画的标签外面嵌套 transition 标签 ,并且设置name属性
Vue 提供了 transition 的封装组件,列表中更新,移除,新增 情形中,可以给任何元素和组件添加进
入/离开过渡
6中class状态 :
进入:
- 1. fade-enter:进入的 初始状态
- 2. fade-enter-to: 进入的 过渡结束状态(2.1.8版及以上)
- 3. fade-enter-active:进入的 过渡效果
离开:
- 1. fade-leave: 离开的 初始状态
- 2. fade-leave-to: 离开的 过渡结束状态(2.1.8版及以上)
- 3. fade-leave-active:离开的 过渡效果
- 介绍: vue-cli 是一个 辅助开发工具 => 代码编译 + 样式 + 语法校验 + 输出设置 + 其他 ...
- 作用: 可以为开发者提供一个 标准的项目开发结构 和配置 开发者不需要再关注其他
- vue-cli 一个 命令行 工具,最新版本也支持 图形化 操作,可快速搭建大型网页应用
- 说明: vue-cli本质上是一个npm包,也需要通过npm去安装下载
npm i -g @vue/cli // 全局安装脚手架 默认安装的最新版本 4.0+
- 安装完成后 可通过 vue命令 来进行检查 脚手架是否安装成功
- 查看版本
vue -V // 查看脚手架版本号 or vue --version // 和上面等价
- 问题 : 默认安装的4.0+ 版本,但是企业很多还在用2.0+版本 怎么破?
- 执行以下命令就可以 2.0 和 4.0 兼得
- 2.0和4.0创建项目的命令是不一样的
npm install -g @vue/cli-init // 安装桥接工具 将2.0的功能补齐到目前的脚手架上
- 注意 : vue生成的模板的有难有易
- 简单业务 => 简易模板
- 复杂业务 => 内容丰富模板
注意: 文件目路径不能有中文
- 创建: 采用 cli 2.0的特性 (生成简易模板)
# 1.heroes 创建的项目名称 $ vue init webpack-simple heroes // webpack-simple 为模板名称 固定写法 # 2.切换到当前目录 $ cd heroes # 3.安装依赖 $ npm install # 4.启动运行项目 $ npm run dev
- 创建: 采用 cli 4.0 特性 (两种 默认 /选填)
- 注意 4.0 +创建项目时 有两种模式, 一种 默认模式 , 一种选择模式,
- 默认模式:一种标准的模板
- 选择模式: 可以根据自己的需求选择需要的工具和模式
- 配置:
- 在vue.config.js中直接配置,例如
module.exports = { lintOnSave: true, // 在保存代码的时候开启eslint代码检查机制 devServer: { // 实时保存、编译的配置段 open:true, // 自动开启浏览器 port: 12306 // 服务运行端口 } }
//重启项目
- yarn serve
|-- node_modules // 项目需要的依赖包
|-- public // 静态资源存储目录
| |-- index.html // 项目主容器文件
| |-- favicon.ico // 项目默认索引图片
|-- src
| |-- assets // 放置一些静态资源文件,例如图片、图标、字体
| |-- components // 公共组件目录
| |-- views // 业务组件目录
| |-- App.vue // 顶层根基路由组件
| |-- main.js // 主入口文件
| |-- router.js // 路由配置文件
|-- .editorconfig // 代码规范配置文件
|-- .eslintrc.js // eslint代码规范检查配置文件
|-- .gitignore // git上传需要忽略的文件格式
|-- babel.config.js // babel配置文件
|-- package-lock.json // 依赖包版本锁定文件
|-- package.json // 项目基本信息配置文件
|-- postcss.config.js // css预处理器配置文件
|-- vue.config.js // webpack 配置文件(与webpack.config.js作用一致)
- require 和 Es模块化的区别
- 介绍: 在cli开发模式下, 一个*.vue文件就是一个组件
- template 组件的页面结构 代表它的 html 结构
- 必须在里面放置一个 html 标签来包裹所有的代码
- 我们在其他地方写好了一个组件,然后就可以在当前template中引入
- script 组件的逻辑结构及数据对象
- style 组件的样式
- 就是针对我们的 template 里内容出现的 html 元素写一些样式
- 注意 : vue-cli的作用就是让我们把精力放在业务编码上,一切准备的工作交给vue-cli去做
任务
- 1. 新建一个名为 Menu的组件(首字母必须大写)的组件
- 2. 内容为 一个横向菜单 首页 新闻 体育 音乐
- 3. 菜单高60px 水平居中 字体大小为20px 颜色为 red 背景色 为 #CCCCCC
- 4. 实现组件在页面上展示
- 项目演示 => 功能拆分 => 路由 => 增 修改 删除 更新
//模拟接口并安装bootstrap PS D:\VCProject\kaikeba\vue-cli> cd template PS D:\VCProject\kaikeba\vue-cli\template> json-server db.json //新开一个终端 PS D:\VCProject\kaikeba\vue-cli> cd vue-pro PS D:\VCProject\kaikeba\vue-cli\vue-pro> cnpm i [email protected]
目标 :将项目所需样式导入到项目中
- 安装 bootstrap固定版本
npm i [email protected]
- 安装完成之后 ,在入口处(main.js)引入js文件
- 在src/components 文件夹中新建组件 head.vue
import "./../node_modules/bootstrap/dist/css/bootstrap.css"; // 引入 import "./assets/index.css"; // 引入index.css
- 1. 新建vue文件
- 2. 拷贝html静态内容到 template中
- 3. 在app.vue中引入组件
- 4. 注册在app.vue的组件中
- 5. 在app.vue的模板中使用注册组件
步骤:
- 1. 安装路由
1. npm i vue-router // 安装路由模块
- 2. 在main.js中引入 路由模块
import VueRouter from 'vue-router' // 引用router Vue.use(VueRouter) // 使用router
- 3. 在vue-cli中使用router
- 4. 配置router-link(app-list.vue)
- router-link上的tag属性 可以指定渲染成什么html元素
英雄列表 ....
- 5. 实例化router 完善路由表(router.js)
- 路由表需要的组件从外部引入
5. import AppList from "./app-list.vue"; import Foo from "./foo.vue"; import Bar from "./bar.vue"; const router = new VueRouter({ // 路由表 routes: [ { path: "/heroes", component: AppList }, { path: "/foo", component: Foo }, { path: "/bar", component: Bar } ] }); // router加入实例 new Vue({ el: '#app', render: h => h(App), router })
- 6. 在App.vue中加入路由承载视图(router-view)
路径:
1. 把路由业务抽取到router.js
- 注意要引入vue
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) Vue.config.productionTip = false import Applist from './list.vue' import Foo from './foo.vue' import Bar from './bar.vue' import Add from './add.vue' import Edit from './edit.vue' const router = new VueRouter({ linkActiveClass: "active", routes: [{ path: '/', redirect: '/heroes' }, { path: '/heroes', component: Applist, }, { path: '/foo', component: Foo }, { path: '/bar', component: Bar }, { path: '/add', component: Add }, { path: '/edit/:id', component: Edit, keepAlive: false }] }) export default router
2. 在最后一行把router对象暴露出去
export default router
3. 在main.js中引入router.js
import router from './router'
步骤:
1. 安装axios 插件
// 1.安装axios 插件 npm i axios
2. 人物列表组件中引入 axios ,
// 2.引入axios,在需要的文件(list.vue)中引入axios import axios from 'axios'
3. 定义data选项定义list列表数据
// 3.定义数据 data() { return { list: [] }; }
4. 请求列表的方法封装 获取数据赋值list列表
// 4.请求人物列表的方法封装 loadData() { //restful规则 axios.get("http://localhost:3000/heroes").then(result => { this.list = result.data; }) }
5. 在mounted事件(相当于window.onload)中调用获取数据方法
// 5.实例完成事件 mounted() { this.loadData(); },
6. 根据数据渲染列表
// 6.根据数据渲染列表
{{item.id}} {{item.name}} {{item.gender}} edit delete
1. 注册删除事件
- 因为删除需要id 所以定义删除方法的时候 把id传进去
// 1.注册删除事件 删除
2. 定义删除方法 实现删除逻辑
3. 判断删除成功 刷新数据
// 2.定义删除方法 // id为要删除id的方法 delItem(id) { if (confirm("确认删除此条数据")) { axios.delete("http://localhost:3000/heroes/" + id).then(result => { // 3. 判断删除状态 是否成功 if (result.status === 200) { this.getData(); // 刷新数据 } }); } }
1. 新建add.vue组件 写入静态内容(拷贝静态资源)
2. 在路由表中配置添加功能的路由
// 2.在路由表中配置添加功能的路由 import Add from './add.vue' { path: "/add", component: Add } // 引入组件 配置路由
3. 给列表组件的添加按钮 添加hash 以对应路由表
// 3.给列表组件的添加按钮 添加hash 以对应路由表 添加
4. 根据业务场景调整页面模板
// 4.根据业务场景调整页面模板
添加人物
步骤: 添加功能的实现
- import axios from 'axios'
1. 定义表单数据 和 表单进行绑定
//文本框添加v-model
//1.添加数据 data() { return { // 定义一个数据对象 存储 姓名和性别 formData: { name: "", // 姓名 gender: "" // 性别 } }; }
2. 给确定按钮 添加点击事件和方法
3. 实现添加方法的逻辑
4. 判断填报信息是否为空
5. 发送axios请求以post方式 调用 添加的接口地址
- 成功返回状态码是201
6. 成功以后 利用编程式导航 跳转到 ’/heroes‘
// 3.确定按钮方法 addHero() { // 4.判断填报信息是否为空 if (this.formData.name && this.formData.gender) { // 5.发送请求 添加人物信息 axios.post("http://localhost:3000/heroes", this.formData) .then(result => { // 注意这里添加成功的状态码 是 201 if (result.status === 201) { // 6. 添加成功之后 要跳转回列表页 // 编程式导航 this.$router.push({ path: "/heroes" }); } else { alert("添加失败"); } }); } else { alert("提交信息不能为空"); } }
步骤 : 实现编辑的显示数据
- import Edit from './edit.vue'
1. 添加编辑路由 注意 由于需要拿到编辑数据的标识 所以需要动态路由
2. 给 编辑按钮 添加 跳转路由的属性
3. 定义获取英雄数据方法
- 1. 通过$router.params来获取动态id
- 2. 根据id发送axios请求 获取英雄数据
4. 在mounted事件中 调用加载英雄方法
// 1.添加动态路由 { path: "/edit/:id", component: Edit } // 编辑组件 动态路由
// 2.编辑按钮添加跳转的属性
编辑 // 3.通过id获取英雄数据 loadHero() { const id = this.$route.params.id; // 通过参数获取id if (id) { //判断id axios.get("http://localhost:3000/heroes/" + id).then(result => { this.formData = result.data; // 获取数据并赋值给表单对象 }); } }
// 4.调用获取英雄数据的方法 mounted() { this.loadHero(); }
步骤 :
1. 定义提交方法
2. 实现提交方法的逻辑
1. 判断提交内容非空
2. 获取动态参数id
3. 发送aixos请求put方式 拼接id 把修改的数据带上
4. 成功以后 利用编程式导航回到 "/heroes"
// 编辑英雄 editItem(){ if (this.formData.name && this.formData.gender) { const id = this.$route.params.id; axios .put("http://localhost:3000/heroes/" + id, this.formData) .then(result => { if (result.status === 200) { this.$router.push({ path: "/heroes" }); } else { alert("编辑失败"); } }); } else { alert("提交内容不能为空"); } } }
1 在入口main.js文件中引入axios,并赋值给全局Vue对象的原型
import Axios from 'axios' Vue.prototype.$http = Axios; // 所有的实例都直接共享拥有了 这个方法
2 调用接口时 采用 实例.属性的方式即可调用,注释单独页面的axios导入
// 把以前用到axios的地方 换成 this.$http
步骤 : axios中配置统一的 请求路径头
1. 给axios中的baseUrl设置常态值
Axios.defaults.baseURL = "http://localhost:3000"; // 设置共享的方法
2. 改造所有的的请求
// 没改造之前 'http://localhost:3000/heroes/' // 设置完常态值 '/heroes/'
基础-案例优化-统一设置激活样式
router.js 的路由表上面加上
linkActiveClass: "active", // active为bootstrap中的 一个class样式