周报
完善案例
this.$nextTick(function () {
this.$refs.input.focus()
})
}
//点击编辑直接获取焦点
this.$refs.input.focus()
//但是这种写法 由于input是用v-show控制的 所以执行了上面代码 改变了isEdit值 但是不会立马去重新解析模板 input框还没有出来
//将handleedit回调执行完之后才会去重新解析 所以获取焦点时还没有出现input框
//使用上方方法 将模板重新解析 DOM更新完毕 input框出现在页面 再执行回调 将input框获取焦点
简单总结vue注意点
- root容器里的代码被称为Vue模板
- Vue实例与容器是一一对应的
- 真实开发中只有一个Vue实例,并且会配合着组件一起使用
{{xxx}}
中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性- 双向绑定一般都应用在表单类元素上(如:
<input>
、<select>
、<textarea>
等)v-model:value
可以简写为v-model
,因为v-model
默认收集的就是value值- el有2种写法:创建Vue实例对象的时候配置el属性 先创建Vue实例,随后再通过
vm.$mount('#root')
指定el的值- 由Vue管理的函数,一定不要写箭头函数,否则this就不再是Vue实例了
- data中所有的属性,最后都出现在了vm身上
- vm身上所有的属性 及 Vue原型身上所有的属性,在Vue模板中都可以直接使用
- 事件的回调需要配置在methods对象中,最终会在vm上
- methods中配置的函数,不要用箭头函数!否则this就不是vm了
- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象
系统修饰键(用法特殊):ctrl、alt、shift、meta 配合keydown使用:正常触发事件
计算属性::要用的属性不存在,需要通过已有属性计算得来。原理:底层借助了
Objcet.defineproperty()
方法提供的getter和setter。计算属性最终会出现在vm上,直接读取使用即可监视属性watch:当被监视的属性变化时,回调函数自动调用,进行相关操作监视的属性必须存在,才能进行监视
- 在watch中配置
deep:true
可以监测对象内部值的改变(多层)- watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
- 所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象
- 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。
用index作为key可能会引发的问题:
- 若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
- 若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题
- 对象中后追加的属性,Vue默认不做响应式处理
- 如需给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value)
vm.$set(target,propertyName/index,value)
Vue.set()
和vm.$set()
不能给vm 或 vm的根数据对象(data等) 添加属性<input type="checkbox"/>
没有配置value属性,那么收集的是checked属性(勾选 or 未勾选,是布尔值)- 生命周期函数中的this指向是vm 或 组件实例对象
一般不会在
beforeDestroy
操作数据,因为即便操作数据,也不会再触发更新流程了school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
我们只需要写<school/>或<school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)
特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!
VueComponent.prototype.__proto__ === Vue.prototype
ref
属性:应用在html
标签上获取的是真实DOM元素,应用在组件标签上获取的是组件实例对象(vc)props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据
组件上也可以绑定原生DOM事件,需要使用
native
修饰符通过
this.$refs.xxx.$on('atguigu',回调)
绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!
vue相关项目
# 初始创建
vue create 项目名称
脚手架目录:public + assets文件夹区别
node_modules:放置项目依赖的地方
public:一般放置一些共用的静态资源,打包上线的时候,public文件夹里面资源原封不动打包到dist文件夹里面
src:程序员源代码文件夹
-----assets文件夹:经常放置一些静态资源(图片),assets文件夹里面资源webpack会进行打包为一个模块(js文件夹里面)
-----components文件夹:一般放置非路由组件(或者项目共用的组件)
App.vue 唯一的根组件
main.js 入口文件【程序最先执行的文件】
babel.config.js:babel配置文件
package.json:看到项目描述、项目依赖、项目运行指令(可以查看vue版本)
README.md:项目说明文件
cmd中 vue -V 查询脚手架版本(5.0.8)
# 配置
1:浏览器自动打开
在package.json文件中
"scripts": {
"serve": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
2.关闭eslint校验工具
创建vue.config.js文件:需要对外暴露
```javascript
module.exports = {
lintOnSave:false,
}
```
3.src文件夹的别名的设置(@代表src文件夹)
创建jsconfig.json文件
```json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": [
"src/*"
]
}
},
"exclude": [
"node_modules",
"dist"
]
}
```
# 路由
1.npm install --save vue-router@3(插件库) 需要在vue2中安装3版本的路由
2.创建路由组件【一般放在views|pages文件夹】
3.新建文件夹router(index.js)创建路由器 路由规则 在main.js里引入路由 路由器
main.js
```javascript
import VueRouter from 'vue-router'
//使用
Vue.use(VueRouter)
//引入创建的路由器
import router from './router'
```
index.js
````javascript
//创建一个路由器
import VueRouter from "vue-router";
//引入路由组件
//配置路由规则 VueRouter本质是构造函数
export default new VueRouter({
//路由
routes: [
{},
{},
{},
{}
]
})
````
4.路由的一个分析
两个非路由组件:Header 、Footer
路由组件:Home、Search、Login(没有底部的Footer组件,带有二维码的)、Register(没有底部的Footer组件,带二维码的)
5.创建非路由组件(2个:Header、Footer)
**非路由组件使用分为几步**
第一步:定义
第二步:引入
第三步:注册
第四步: 使用
6.**注册完路由后 路由组件 非路由组件上都有$route $router**
```javascript
$router:进行编程式导航的路由跳转
this.$router.push|this.$router.replace
$route:可以获取路由的信息|参数
this.$route.path
this.$route.params|query
this.$route.meta
```
7.项目采用的less样式,浏览器不识别less语法,需要一些loader进行处理,把less语法转换为CSS语法
**安装less less-loader@7**
切记less-loader安装5版本的,不要安装在最新版本,安装最新版本less-loader会报错,报的错误setOption函数未定义
**需要在style标签的身上加上lang="less",不添加样式不生效**
8.路由的跳转
路由的跳转就两种形式:声明式导航(router-link:务必要有to属性)
编程式导航push||replace
编程式导航更好用:因为可以书写自己的业务逻辑
9.路由传参
params参数:路由需要占位,程序就崩了,属于URL当中一部分
query参数:路由不需要占位,写法类似于ajax当中query参数
创建路由器 路由规则
//创建一个路由器
import VueRouter from "vue-router";
//引入路由组件
import Home from '@/pages/Home'
import Login from '@/pages/Login'
import Register from '@/pages/Register'
import Search from '@/pages/Search'
//配置路由规则 VueRouter本质是构造函数
export default new VueRouter({
//路由
routes: [
{
path: '/home',
component:Home
},
{
path: '/login',
component:Login
},
{
path: '/Register',
component:Register
},
{
path: '/Search',
component:Search
},
//重定向:项目跑起来的时候 立刻定向访问哪里
{
path: '*',
redirect:'/home'
}
]
})
路由传参
最常用对象写法
**传递params参数 需要配置name 不是path**
1:如何指定params参数可传可不传?
路由要求传参 并且已经占位 但是没有传递参数 路径会出现问题
在占位的时候在后面加上问号 解决路径问题
2:params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
使用undefined解决 keyword:''|| undefined
重写push replace
编程式导航路由跳转到当前路由(参数不变), 多次执行会抛出NavigationDuplicated的警告错误?
注意:编程式导航(push|replace)才会有这种情况的异常,声明式导航是没有这种问题,因为声明式导航内部已经解决这种问题。
这种异常,对于程序没有任何影响的。
为什么会出现这种现象:
由于vue-router最新版本,引入了promise,当传递参数多次且重复,会抛出异常,因此出现上面现象,
**第一种解决方案:是给push函数,传入相应的成功的回调与失败的回调**
第一种解决方案可以暂时解决当前问题,但是以后再用push|replace还是会出现类似现象,因此我们需要从‘根’治病;
//先把VueRouter原型对象push先保存一份 push方法存在于VueRouter的原型对象上
let originPush = VueRouter.prototype.push
let originReplace = VueRouter.prototype.replace
//重写push|replace
VueRouter.prototype.push = function (location, resolve, reject) {
if (resolve && reject)
{ //call方法调用可以改变this指向问题 this指向实例而不是window
originPush.call(this,location,resolve,reject)
}
else{
originPush.call(this,location, () => {}, () => {})
}
}
VueRouter.prototype.replace = function (location, resolve, reject) {
if (resolve && reject)
{
originReplace.call(this,location,resolve,reject)
}
else{
originReplace.call(this,location, () => {}, () => {})
}
}
# Home组件
## 拆分组件
一共要拆分为七个组件 (左侧三级联动 轮播以及快报 优质好货 热卖排行 猜你喜欢 家用电器以及手机通讯 各大公司)
### 三级联动
在Home Search Detail都使用 可以注册为全局组件
## 发请求获取服务器数据进行展示
## 开发动态业务
拆分组件:结构+样式+图片资源
注册为全局组件 在home里面直接使用 不需要引入
//将三级联动注册为全局组件
import TypeNav from './pages/Home/TypeNav/TypeNav'
//参数为 组件的名字 哪个组件
Vue.component('TypeNav', TypeNav)
遗留问题:将TypeNav注册为全局组件后 在home中使用 没有效果 局部引入也没有效果
在App中尝试局部引入 可以 但是必须使用条件渲染 尝试很长时间 还是不知道为什么全局注册 在
home中无法使用 (啊啊啊啊啊 为什么呀)
复习操作数组数组的方法
push方法可以向数组的末尾添加一个或者多个元素,并返回新的长度.
pop() 方法用于删除并返回数组的最后一个元素。
unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
isArray() 这个方法用来判断一个对象是不是数组,是的话返回true,否则返回false
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
参数:currentValue当前元素的值
index当前元素的索引值
arr当前元素属于的数组对象
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
filter() 不会对空数组进行检测。
filter() 不会改变原始数组。
参数:currentValue当前元素的值
index当前元素的索引值
arr当前元素属于的数组对象
every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
every() 方法使用指定函数检测数组中的所有元素:
如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
如果所有元素都满足条件,则返回 true。
every() 不会对空数组进行检测。every() 不会改变原始数组。
参数:currentValue当前元素的值
index当前元素的索引值
arr当前元素属于的数组对象
splice() 方法用于添加或删除数组中的元素。
这种方法会改变原始数组。
如果仅删除一个元素,则返回一个元素的数组。 如果未删除任何元素,则返回空数组。
参数:index 必须,规定从何处添加/删除元素。该参数是开始插入和删除的数组元素的下标,必须是数字
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
如果没有找到匹配的字符串则返回 -1。
indexOf() 方法区分大小写。
参数:search value 必须,规定需要检查的字符串值
start 可选,规定在自负串开始检索的位置,如果省略,则将从字符串的首字符开始检索
forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
还未整理完