可视化/数字孪生专业社区
资源中心
问答
文章
实用工具
ByteVCharts
开源中台
申请建模
申请帮助
登录
注册
申请协助
此单为
付费
协助
×
为协助帮威客用户快速入门,帮威客平台可损供用户特定项目的框架代码开发服务。该服务可为用户快速构建符合项目基本需求的3D可视化框架代码资源(包括源码、3D模型、贴图、数据等),用户的技术团队可在此基础上快速上手,大幅提高3D可视化项目成功基础。
预算金额
公司名称
联系人
微信号
手机号码
提交申请
申请协助
此单为
付费
协助
×
为协助帮威客用户快速入门,帮威客平台可损供用户特定项目的框架代码开发服务。该服务可为用户快速构建符合项目基本需求的3D可视化框架代码资源(包括源码、3D模型、贴图、数据等),用户的技术团队可在此基础上快速上手,大幅提高3D可视化项目成功基础。
预算金额
公司名称
联系人
微信号
手机号码
提交申请
业务咨询
开发咨询
微信咨询
杜老师
黄老师
熊老师
支付信息
×
购买文章
Vue基础教程
订单金额
¥
0
实付金额
¥
0
我已阅读并同意ByteV组件购买协议
取消
提交订单
支付宝支付
微信支付
提交订单
1
点赞
1
评论
收藏
分享
举报
Vue基础教程
枸杞
关注
已关注
0
1
1
2543
发表于 2020-05-27 09:53:36
# Vue ## 基础语法(单向数据绑定) ```javascript //引入vue.js的包 //实例化一个Vue var vm = new Vue({ el:'页面元素',//指定但钱要创建的整个vm实例,要控制页面上那个区域的元素(V) data:{//要渲染的数据(M) }, methods:{//这里可以定义事件处理函数 将函数名设置到v-on:click='函数名()' 函数名(){} }, filters:{//私有过滤器 函数名(){} }, directive:{//自定义指令 指令名:{//标准方式 bind(el,binding){}, inserted(el,binding){} }, 指令名:function(el,binding){ //简写方式 当bind和inserted中程序一样时可以写成一个函数 表示bind和inserted中都执行这段代码 } } }) vm.$mount('页面元素') //这样也可以给vm指定要控制的页面元素 ``` + **v-text** 标签属性语法,叫做指令 + 在Vue中,所有的指令,都是属性,都是以v-开头的 + el中的元素可以直接通过{{}}访问到data里面属性 且双花括号只能在标签内容里面使用不能在标签的属性上使用 + 这种{{}}语法,叫做插值表达式,里面可以写任何js代码 + 使用插值表达式,存在内容闪烁的问题,但是`v-text`这种指令方式不会 + 插值表达式中可以使用v-cloak 方式解决闪烁问题(给元素添加该属性,并选中设置隐藏,该属性默认会在元素内容渲染完毕时去掉) + **v-html属性** 将属性值当作元素内容渲染 并且识别标签 + **v-bind:id** 可以让id这个属性识别vue数据和js表达式 可以简写成:id ## 事件 > v-on:click='函数名()' 简写为 @click='函数名()' + 在methods中可以通过this访问data中的数据,this指向实例化出来的vm + 当data中的数据变化时 vm会监听到 并自动更新内容 + 阻止事件冒泡 ``` @click.stop='函数名()' ``` + 阻止默认事件 ``` @click.prevent='函数名()' ``` + 开启事件捕获模式(事件处理函数在事件捕获阶段执行不在冒泡阶段) ``` @click.capture='函数名()' ``` + 只有事件在元素本身上触发时触发(没有阻止冒泡) ``` @click.self='函数名()' ``` + 事件只触发一次 ``` @click.one='函数名()' ``` ## v-model双向数据绑定 + v-bind 只能实现单向数据绑定 从data自动同步到view上 + v-model 实现了数据的双向绑定 且在vue中只有该指令为双向绑定 + v-model 只能应用在表单中 **eval()将一段字符串解析为js代码** ## vue-resource 插件 发送ajax请求 - 用法和axios相似 - 既可以使用全局的Vue对象调用 Vue.http.method() - 也可以在一个实例被调用 this.$http.method() - 除了get和post之外也可以发送jsonp请求 ``` // 基于全局Vue对象使用http Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback); Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback); // 在一个Vue实例内使用$http this.$http.get('/someUrl', [options]).then(successCallback, errorCallback); this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback); ``` - 目前官方已经不在维护 vue-resource 推荐使用axios发送ajax ## 使用axios发送ajax - 请求方式包含 ```js axios.request(config) axios.get(url[, config]) axios.delete(url[, config]) axios.head(url[, config]) axios.post(url[, data[, config]]) axios.put(url[, data[, config]]) axios.patch(url[, data[, config]]) NOTE:在使用别名方法时, url、method、data 这些属性都不必在配置中指定。 ``` 详细config选项[参照](https://www.kancloud.cn/yunye/axios/234845) - 用法一 ```js axios('/user/12345?id=1');//默认发送get请求 ``` - 用法二 ```js axios.get('/user?ID=12345') .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); ``` - 用法三 ```js axios.get('/user', { params: { ID: 12345 } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); ``` - 用法四 ```js axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } }); ``` - 用法五 : 执行多个并发请求 ```js function getUserAccount() { return axios.get('/user/12345'); } function getUserPermissions() { return axios.get('/user/12345/permissions'); } axios.all([getUserAccount(), getUserPermissions()]) .then(axios.spread(function (acct, perms) { // 两个请求现在都执行完成 })); ``` - 创建一个axios实例 ``` var instance = axios.create({ baseURL: 'https://some-domain.com/api/', timeout: 1000, headers: {'X-Custom-Header': 'foobar'} }); ``` - 请求的响应结构 ```js { // `data` 由服务器提供的响应 data: {}, // `status` 来自服务器响应的 HTTP 状态码 status: 200, // `statusText` 来自服务器响应的 HTTP 状态信息 statusText: 'OK', // `headers` 服务器响应的头 headers: {}, // `config` 是为请求提供的配置信息 config: {} } ``` - 默认配置 ```js //全局的axios默认配置 axios.default.baseUrl = 'https://api.example.com'; axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; // 创建实例时设置配置的默认值 var instance = axios.create({ baseURL: 'https://api.example.com' }); // 在实例已创建后修改默认值 instance.defaults.headers.common['Authorization'] = AUTH_TOKEN; ``` - 给响应或者请求添加拦截器 在请求或响应被 `then` 或 `catch` 处理前拦截它们。 ```js // 添加请求拦截器 axios.interceptors.request.use(function (config) { // 在发送请求之前做些什么 return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); }); // 添加响应拦截器 axios.interceptors.response.use(function (response) { // 对响应数据做点什么 return response; }, function (error) { // 对响应错误做点什么 return Promise.reject(error); }); ``` - 移除拦截器 ```js var myInterceptor = axios.interceptors.request.use(function () {/*...*/}); axios.interceptors.request.eject(myInterceptor); ``` - 配置validateStatus自定义状态码的错误范围 ``` axios.get('/user/12345', { validateStatus: function (status) { return status < 500; // 状态码在大于或等于500时才会 reject } }) ``` ## 类操作 - 数组/对象类样式(数组里面识别js代码) ``` v-bind:class='['red','small',isthin?'thin':'']' ``` 或者 ``` v-bind:class='['red','small',{thin:isthin}]' ``` 或者 ``` v-bind:class='{thin:isthin}' ``` 直接操作data里面的isthin即可 ## 行内样式操作 ``` :style={color:'red'} ``` 或者 ``` :style=obj//data操作obj:{color:'red'} :style=[obj1,obj2] ``` ## 数据渲染 - 遍历data中list数组 ```
{{item}}
或者
{{i}}---{{item}}
``` - 遍历data中对象list ```
{{val}}
或者
{{key}}---{{val}}
或者
{{key}}---{{val}}-{{i}}
``` - 当in一个数值的时候 ```
{{item}}---{{i}}
//item从1到9 i从0到8 ``` - :key 只要涉及到了 v-for这种循环 推荐给循环的每一项添加key属性 且属性值必须具有唯一性 (用来记录上一次操作的项) ## 元素的显示和隐藏 - v-if='bool' 和v-show='bool' 为真则显示否则隐藏 - 区别 - v-if 是实时创建或移除元素 从而达到显示或者隐藏 - v-show 是通过display:none 来操作的 - 频繁切换使用 v-show比较好 初始渲染消耗高 - 运行环境不可能被改变的时候使用 v-if 切换消耗比较高 ## 循环 ``` //得到符合某种条件的项的索引 var index=arr.findIndex(function(item,i,arr){ return 某种条件 }) ``` **字符串方法** str.includes(str1) str1是否包含于str中 **数组方法** arr.filter(function(item){}) 循环指定数组 并把满足回调函数中指定条件的项返回 从而的到一个新数组 ``` arr.filter(function(item){ return 某种条件 }) ``` ## 过滤器 - 自定义一个全局的过滤器 ``` Vue.filter('过滤器名称',function(要过滤的数据,参数2...){ ...//过滤程序 rturn 过滤后的数据 }) ``` - 过滤器的调用 ```
{{item.id|过滤器名称1|过滤器名称2(参数2)}}
// |为管道符 是用来调用过滤器的 后面的括号是用来传参的 从第二个参数开始传 第一个参数永远是管道符前面的数据 ``` - 过滤器的处理函数必须返回一个数据 ,已被输出或者下一个过滤器操作 - 可以连续使用管道符 调用多个过滤器 - 只有在v-bind: 和插值表达式中可以使用过滤器 - v-text中不识别过滤器 - 如果全局过滤器和私有过滤器重名 会优先使用自身私有的 ## vue滑动滚动better-scroll [http://blog.csdn.net/TionSu/article/details/77651051]() ## 自定义指令 **定义全局获得焦点的v-focus指令** ``` Vue.directive('指令名称',{ bind:function(el,binding){ //当指令绑定到的元素,被Vue实例解析的时候会立即执行 el.focus()//这时el并没有被插入到文档,所以focus不生效,需要写在inserted中 el.style.color='red'//样式不管何时设置都会生效,行为则需要在el存在式才会设置生效 }, inserted:function(el,binding){ //当指令绑定到的元素,被插入到文档的父节点时候,会立即执行 }, }) ``` - 自定义指令的名称不需要写v-前缀,内部默认会加上,所以调用的时候需要加上 - 指令函数的参数列表中第一个参数永远是el 表示被绑定指令的那个元素 - 第二个参数binding,是一个对象包含下列属性 - name 指令名称(不包括前缀) - value 指令名称所对应的值 - expression 指令名称所对应的计算值之前的表达式,是一段字符串 ## 键盘事件 - @keyup.enter 回车键弹起的时候 - @keyup.任意键标识符 ## 声明周期函数(钩子函数) ``` //页面打开或者刷新都会触发周期函数 var vue = new Vue({ el:'', data:{}, methods:{}, beforeCreate:function(){//周期函数 此时 data和methods中的属性和方法还没有初始化好 }, created:function(){//周期函数 data和methods中的属性和方法可以随意调用了 }, beforeMount:function(){//周期函数 html代码解构已经在内存中完全创建好了,但是还没有添加到页面,即将添加或者挂载 }, mounted:function(){//周期函数 页面渲染完毕 vue创建阶段结束 可以在这里操作dom元素了 } }) ``` 主要的生命周期函数分类: - 创建期间的生命周期函数: - beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性 - created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板 - beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中 - mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示 - 运行期间的生命周期函数: - beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点 - updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了! - 销毁期间的生命周期函数: - beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。 - destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 ## 动画(过渡类) - v-enter-active 入场动画这个时间段 - v-enter 入场之前的状态 时间点 - v-enter-to 进入之后动画结束时的状态 时间点 - v-leave-active 出场动画这个时间段 - v-leave 出场之前的状态 时间点 - v-leave-to 出来之后动画结束时的状态 时间点 1.在vue中如果要让一个元素产生动画 必须使用 transition整个标签包起来 2.必须使用v-if或者v-show来控制 **动画结合外部类** enter-active-class='外部类名' 表示入场这个过程中使用这个外部类,比如animation.css的一个动画类 > 像下面这样 如果要引用animate.css中的类 首先要给做动画的元素加上 animated这个类 然后给transition标签加上 入场类和出场类 > > 入场类enter-active-class="bounceInDown" 出场类leave-active-class="bounceOutDown" > > 控制flag来做动画 ```
哈哈哈哈哈哈哈
``` **js钩子(动画的生命周期函数)** @before-enter 起始状态 @enter 结束状态 @affter-enter 结束后的回调 可以使用done()在enter中被调用 例子: ```javascript
``` **多个元素动画(列表过渡)** transition-group标签将要做动画的一组标签包起来 并且给这一组标签分别添加唯一:key属性 用v-for循环渲染 ```html
``` transition-group标签的tag属性 tag='ul' 把该标签渲染为一个ul标签 transition 的mode属性 (动画顺序) v-move 元素定位改变的时候的选中类 有一个缓冲的效果 transition的name属性可以修改过渡类的前缀 用来标识这些前缀的过渡类只能操作 name为该前缀的这一组元素 ## 组件化(小型Vue实例) > vue组件就是一个小型的vue 可以有自己的私有数据data 但是必须是一个function 这个函数必须返回相应的数据 也有私有的methods > 为什么data要定义一个function 因为 每当页面引用一次组件,必然会线调用整个函数 , 从而得到私有的数据对象 return一个字面量对象会在堆中创建新的对象 return一个引用对象的话 每次引用组件使用的都是同一个数据 >Vue也可以看作是一个组件 所有的组件都是Vue的子组件, 子组件也可以看作是一个小型的Vue > 组件中也有自己的声明周期函数 和Vue实例一样 > 引用组件的地方,需要是Vue实例所渲染的html元素中 1. **创建全局组件的第一种方式(component):** ```javascript const com1 = Vue.extend({ template:'
',//表示这个组件的代码解构 data:function(){ return 数据对象 } })//com1是一个构造函数 ``` 注册全局组件: ```javascript Vue.component('mycom1',com1)//mycom1是组件名不能包含大写 可以使用连字符 ``` 引用全局组件: ```html
``` 2. **创建全局组件的第二种方式:** ```javascript const obj = {//组件对象 template:'
' } Vue.component('mycom2',obj)//注册组件 ``` 引用 ```html
``` **Vue.component**(属于小型vue实例)的第二个参数即接收一个组件的构造函数 也接受一个对象 **template**中不能只放文本 必须包裹标签 不能直接放多个标签 必须用一个标签包起来 3. **创建全局组件的第三种方式:** ```javascript Vue.component('mycom3',{ template:'#box'//然后在html中定义一个id为box的template标签 }) ``` ```html
这里也是只能放一个根元素
//定义组件的模板结构 (数据模板不会被渲染) ``` 1. template标签不会被直接渲染 只有当mycom3被引用的时候才会渲染 2. template标签如果在一个vue的实例的标签结构中 会被直接渲染出来 4. **创建私有组件** ```javascript var vm = new Vue({ el:"", components:{//注意这里components 后面有说明可以多个组件 'mycom4':{ template:'#id', data:function(){ return 数据 } } } }) ``` - **多组件切换** ```javascript
//代替了组件名的标签方式 和组件名标签等价 //注意 is的值不能直接写组件名(会把这个值当作变量解析) 要使用变量代替 ``` 通过切换组件的名称来切换显示不同的组件 - **父组件向子组件传值** - 默认子组件无法直接获取父组件中的数据 解决方法:(如果传递父组件的方法则使用绑定事件的方式而不是绑定自定义属性) ```html //父组件
//子组件
//自定义msg属性绑定父数据
``` ```javascript Vue({ el:'#box' data:{ 父数据:'' } component:{ mycom:{ template:'
{{msg}}
',//使用数据 props:['msg']//接收绑定好的msg this.msg可以拿到整个msg } } }) ``` - props的数据不要直接拿来修改 如果想要修改必须在data上重新定义一个属性 将要修改的数据赋值给这个新定义的属性 然后修改整个新的属性的值 - props中的数据只能通过this读取不能修改(比如this.msg) 不能写入 **传递方法:** ```html //父组件
//子组件
//如果传递父组件的方法则使用绑定事件的方式而不是绑定自定义属性
``` ```javascript Vue({ el:'#box', methods:{ fadd:(接收子组件传过来的参数)=>{//父方法 } }, component:{ mycom:{ template:'
',//使用数据 methods:{ add(){ this.$emit('fn',向父方法中要传的参数)//这一行代码就是在调用父方法 可以把子组件数据传递给父组件 } } } } }) ``` ## $refs的使用(获取vue子元素和子组件的属性和方法) - 可以通过给标签定义ref属性标识这个元素, 在一个Vue实例中可以用过this.$refs.myh3获取这个h3标签 ```javascript
``` - this.$refs.myh3可以获取子组件的属性和方法(前提是**子组件**的标签定义了ref属性 ref='myh3') 必须是子组件的标签定义该属性 不能是上一级或者下一级元素 ## 路由/vue-router.js插件 - `#` 锚链接 hash值 不会刷新页面 不会发送到后台 - location.hash可以获取hash值 - onhashchange事件 - 前端路由: 根据不同的hash地址,在页面上切换不同的组件 1. vue-router的基本使用 - 引入vue-router.js插件 - new VueRouter({}) *router-link-active* 这个类可以选中当前被点击的锚链接 ```html
//前面的#号可以省略 如果要在hash中拼接变量需要这样 :to="'has'+变量"
// 路由配置 /login/:id/:name 无需#号 id为10 name为'zs'
// 呈现匹配到的has值对应的内容 //router-view 默认不渲染为元素 //router-link 默认渲染为a链接 可以通过这个标签的tag属性来更改为相应的标签 ``` ```javascript //不同hash值显示相应的组件 obj={//定义组件 props:['id','name']//定义好用来接收参数的id 和name 这个方法只能在新版的Vue中使用 template:"", ... } ... const router = new VueRouter({//创建路由对象 routers:[//路由规则 锚链接后面使用?传参不需要修改路由规则 ?后面的可以不写 但是如果是url形式的 必须写 如'/login/:id/:name' 写成这样的格式 //this.$router.query 可以获取锚链接后面?传递的参数(obj) //this.$router.params 可以获取锚链接后面url地址(/:id/:name)专递的参数(obj) {path:'不带#号的hash',component:组件对象obj}, {path:...,redirect...}//重定向到另一个hash {path:'/login/:id/:name',component:obj}//url地址栏传参 {path:'/login?id=3',component:obj}//?传参 {path:'/login/:id',component:obj,props:true}//表示可以通过props数组获取参数 前提必须在obj组件对象中定义好参数 {path:'/account/',component:obj,children:[ {path:'login',conponent:}//配置子路由规则 前面不能加斜线和父hash 链接和坑也要放在父路由的模板里面 ]} ], linkActiveClass: '默认为router-link-active 可以进行自定义 这个类可以选中当前被点击的锚链接 进而修饰被选中的锚链接' }) new Vue({ router:router//挂载路由对象(如果名称和值相同 可以省略只写名称) }) ``` ## 命名视图(一个hash对应多个组件) ```html
``` ```javascript const router = new VueRouter({ routers:[ {path:'/',component:{//一个hash对应多个组件 'top':header组件, 'left':sidbar组件, 'right':content组件, 'bottom':footer组件 }} ] }) ``` ## watch属性监听数据改变 - 例子 ```javascript var vm = new Vue({ el:'', data:{ firstname:'' }, watch:{//表示监听指定数据的改变 'firstname':function (newval,oldval){//监听firstname的变化 newval 新数据 oldval 旧数据 } } }) ``` - 应用场景:监听单个的虚拟的数据的改变 比如监听url地址 ```javascript var vm = new Vue({ el:'', data:{ firstname:'' }, watch:{//表示监听指定数据的改变 数据改变才会触发 '$route.path':function(newval){//监听hash地址 } } }) ``` ## computed 计算属性 1. ``` var vm = new Vue({ el:'', data:{ firstname:'', lastname:'' }, computed:{//计算属性 计算属性中所依赖的任何数据发生变化 就会触发计算属性重新求值 fullname就是计算属性不在data之中 但是页面会把这个属性当作普通属性来用 实现数据的绑定 'fullname':function(newval){ return this.firstname+this.lastname } } }) ``` 2. get和set ``` var vm = new Vue({ el:'', data:{ firstname:'', lastname:'' }, computed:{//计算属性 计算属性中所依赖的任何数据发生变化 就会触发计算属性重新求值 fullname就是计算属性不在data之中 但是页面会把这个属性当作普通属性来用 实现数据的绑定 'fullname':{ get(){//当依赖数据改变时 返回一个实时的计算结果 return this.firstname+this.lastname//函数内部用到的数据都是依赖数据 }, set(){//当计算属性改变时 也可以去同步更改所依赖的数据 } } } }) ``` ## 使用cnpm工具下载包 - 在nrm中 cnpm只是一个镜像的地址而已 - 在cnpm这个工具中 就像npm一样 去下载和安装包 - 只不过安装命令 是cnpm开头 - ``` npm install cnpm -g --registry=http://registry.npm.taobao.org ``` ## webpack前端项目构建工具 - 解决静态文件之间复杂的依赖关系 - 合并压缩静态文件 避免二次请求 把图片转化为base64的格式 压缩文件体量 - 能够把高级的语法转化为低级的语法 - 能够自动转换一些模版文件比如.vue=>.js 以让浏览器识别 - 适合结合单页面应用程序使用,不适合应用于多页面应用程序 - 安装webpack - 全局安装`cnpm i webpack -g` - 项目中安装`cnpm i webpack -D`安装到项目的开发依赖 **ES6中提出了import和export的概念**(但是目前谷歌不支持)需要使用webpack将文件打包成谷歌所识别的低级的语法 - import $ from 'jquery' 导入jquery模块 - 导出模块 export default { } - 打包文件 `webpack 要处理的文件的路径(相对于命令行路径) 处理好的文件的路径` - 快捷打包方式 输入`webpack`即可 但是需要在项目根目录创建`webpack.config.js`的文件 而且在这个配置文件中,必须显示声明 要处理的文件的路径 和输出的文件路径 (webpack基于node开发支持node语法 所以这个文件可以使用node语法) 配置如下: ```javascript const path = require('path') // 导入 把 HTML 页面生成到内存中的插件(需下载) const htmlWebpackPlugin = require('html-webpack-plugin') // 导入的是一个构造函数 // 导入指定浏览器的插件(需下载) (选择默认打开那个浏览器的插件) const openBrowser = require('open-browser-webpack-plugin') // 导入webpack const webpack = require('webpack')//在本文件启用热点更新的前提 module.exports = { entry:path.join(__dirname,'./src/main'),//要处理的js文件路径 output:{//指定输出文件的配置 path:path.join(__dirname,'/dist'),//指定输出文件的存放路径 filename:'bundle.js'//指定输出文件的名称 }, plugins:[//配置插件的数组 new htmlWebpackPlugin({ // 创建一个把HTML首页托管到内存中的插件 template: path.join(__dirname, './src/index.html'), // 要把哪个HTML页面,作为模板,复制一份托管到内存中 filename: 'index.html' // 指定,将来在内存中复制出来的页面,名称叫做 index.html }), /* new openBrowser({ // 打开指定浏览器 browser: 'firefox', url: 'http://127.0.0.1:3000' }), */ new webpack.HotModuleReplacementPlugin()//在本文件启用热点更新的前提 ], devServer:{//这里也可以设置webpack-dev-server运行时候的指令 必须将package中配置的这些去掉(不推荐这样配置) open:true,//自动打开浏览器 port:3000,//托管的端口 host:'127.0.0.1',//主机 hot:true,//启用热更新 需要配合一个插件才能使用(导入webpack模块) } } ``` 代码发生改变需要重新打包 体验不好 - webpack-dev-server 实时监听项目的改变 并自动打包(把项目默认托管到了本地的8080端口) - 必须在项目本地安装webpack - 然后安装 webpack-dev-server 到项目 - 在package.json文件中的scripts中加一项配置`"dev":"webpack-dev-server"` - 在命令行执行`npm run dev` 以执行dev脚本,启动webpack这个实时创建的服务器 之后修改代码 webpack会实时监听并且自动更改内存中的数据 自动刷新网页在网页中呈现内存的更改 (而实际磁盘上的bundle.js并不会更新或者打包) - 如果需要打包 或者更新 需要执行`webpack`命令 - 输出的文件bundle.js 并没有存放到实际的物理磁盘中,而是被托管到了内存中,可以认为 在项目的根目录有一个虚拟的bundle.js - html-webpack-plugin插件 > 自动在内存中生成一个一样的页面 自动引入打包好js文件 - npm 安装这个项目插件 - 在webpack配置文件中 载入这个模块 - 然后配置一项和output平级的plugins项 ``` plugins:[//插件的数组 new htmlWebpackPlugin({//创建一个把html首页托管到内存中的插件 tempalte:path.join(__dirname,'./src/index.html'),//把要托管的页面,作为模板,赋值一份托管到内存中 filename:'index.html'//指定将来在内存中复制出来的页面的名称 }) ] ``` - 运行 npm run dev以执行更改后的dev脚本 (对配置进行更新) 每当修改webpack的配置文件后都要 进行这一步(重启webpack服务器) - 在package.json文件中的scripts中加一项配置`"dev":"webpack-dev-server --open --port 3000 --host 127.0.0.1 --hot"` > 这段配置 可以在编译完之后自动打开浏览器 项目托管到3000端口 127.0.0.1的地址中 指定--hot会让更改以补丁的形式编译上传,效率较高 如果不指定则会全部重新生成 **webpack打包其他格式的文件** > 默认webpack只能打包js文件 不能打包其他格式的文件 - **如果要打包css格式的文件**需要 安装并配置两个适合的loader(开发依赖项) - style-lader `npm i style-laoder -D` - css-loader `npm i css-laoder -D` - 配置webpack.config.js ``` //添加一项module选项 module:{ rules:[//非js文件和loader之间的对应关系 {test:/\\.css$/,use:['style-loader','css-loader']}创建css文件的loader匹配规则 ] } ``` - 然后就可以将css文件引入main中 ``` import './css'或者 import mycss from './css' ``` - **如果要让webpack打包less文件**需要安装less `npm i less -D` - 安装less-loader `npm i less-loader -D` - 在webpack.config.js中的module的rules选项中添加匹配规则 ``` {test:/\\.less$/,use:['style-loader','css-loader','less-loader']} ``` - 然后就可以在main.js中直接引入less文件了 - **如果想要打包scss文件** 需要安装 sass-loader和node-sass (是sass-loader内部依赖项不需要配置)然后配置webpack.config.js 即可 ``` {test:/\\.less$/,use:['style-loader','css-loader','sass-loader']} ``` - **如果要处理样式表中的图片路径** 需要 安装炳配置 url-loader和file-loader(是url-loader的内部依赖项) 然后配置webpack.config.js 即可 ``` {test:/\\.jpg|png|gif|bmp$/,use:'url-loader?limit=1190&nam=[hash:8]-[name].[ext]'}//如果只有一个loader不写数组也可以 limit表示图片的大小限制单位Byte(字节) 图片大于这个limit会自动将图片转换为base64位的格式 否则不转 [hash:8]-[name].[ext] 重名名的时候取前8位-自己的原文件名.后缀名 ``` - **使用babel处理ES6和ES7中一部分新特性** - 还是有一部分新的特性webpack是不能处理的 ```javascript //比如 class Person { static info={name:'zs'} } ``` - 需要下载安装两套相应的loader - babel-care babel-loader babel-plugin-transform-runtime -D - babel--preset-env babel--preset-stage-0 -D > 以bael-preset 开头的包叫做语法 > > 以bael-pugin开头的叫做插件 - 配置webpack.config.js ``` {test:/\\.js/,use:'babel-loader',exclude:/node_modules/} ``` > 添加转换js文件的loader,其中 ,必须把node_modules目录设置为排除项 这样在打包的时候 就会忽略nodemodules (不需要转换) - 根目录新建名字叫.babelrc的文件,配置如下 ``` { "plugins":["transform-runtime"], "presets":["env","stage-0"] } ``` > 这样就可以将高级的js语法转换为低级的了 ## 项目发布 - 根目录复制一份配置好的webpack.publish.config.js - 安装依赖的包 - 在package.json中的scripts中加一项配置如下 ``` "pub": "webpack --config webpack.publish.config.js" ``` - 在项目下执行npm run pub即可将项目打包为发布版 ## class关键字,以及ES6中的导入和导出 - 导出 `export default { a }` - export default 在一个文件中只能使用一次 - export 可以多次使用 比如还可以这样导出`export var a=10` - 导入 `import 变量名 from '路径(模块标识符)'` - 这种方式只能拿到 `export default导出的成员 拿不到export导出的成员` - 可以使用`import {成员名 as 变量名} from '路径(模块标识符)'按需导入export暴露的成员 并用as重命名 > 注意这里的{}不是解构赋值 是按需导入 解构赋值重命名是: 而这里的重命名是用as - class 关键字 ``` class Person { //定义类名(构造函数的名称) constructor(){//定义构造函数 this.name=name this.age=age } //static 专门用来创建静态属性或者方法的(构造函数这个对象下面的方法和属性) static info = '这是使用class关键子定义的类' show(){ //这是一个实例方法(构造函数实例出来的对象下面的方法) } } ``` 静态属性:直接使用构造函数 点出来的属性 实例属性:通过构造函数创建出来的实例下面的属性 - 在class等分{}作用域中 只能写constructor, 静态属性,静态方法,实例方法 - 在class类中必须要有一个canstructor 如果没有写 则系统默认会提供一个看不见的constructor - 如果定义了constructor, 则会覆盖看不见的那个constructor **继承** ```javascript class GDRen extends Person { constructor(name,age,eating){ super(name,age)//调用父类的构造,继承属性 this.eating=eating } } ``` - super() 父类构造函数的引用 - 如果子类通过extends实现了继承 那么子类的构造函数中必须先调用一下super这个父类的构造函数 ,才能在内部使用this - 这样就继承了父类的方法和属性 ## Fetch API (代替传统的XHR对象 发送ajax) ``` fetch(url).then(function(response){ return response.json()//如果请求成功了这里拿不到最终的数据 }).then(result=>{ console.log(result)//拿到请求的数据 }).catch(function(err){ }).finaly(function(){ 完成进入 }) ``` ## Promise - Promise是一个构造函数,用来构造异步操作的 ``` const p = new Promise()//表示构建了一个形式上的异步操作 //在参数列表中可以传递一个匿名函数就,就代表一个具体的异步操作 new Promise(function(){}) ``` - Promise这个对象上有resolve和reject两个方法,其中resolve表示成功的回调函数reject表示失败的回调函数 - 在Promise.prototype上有个then函数,这个then表示为Promise指定成功和失败的回调函数(then函数可以传递两个参数,第一个是定义成功的回调函数,第二个是定义失败的回调函数) ``` Promise实例.then(成功的回调resolve,失败的回调reject) ``` - 应用: Promise是ES6中提出来的,来及决异步函数嵌套问题的 (回调地狱) - 只要new出来Promise对象,那么传入的异步操作就会立即执行,需要再封装一层函数才能按需执行 - 例子: 封装一个nodejs读取文件的函数 ```js const fs = require('fs') //封装 function readFilePromise(fpath){ const p = new Promise(function(resolve,reject){ fsreadFile(fpath,'utf-8',(err,result)=>{ if(err) return reject(err)//如果失败了调用这个失败的回调函数 resolve(result)//如果成功了调用这个成功的回调函数 }) }) return p } //调用 readFilePromise(__dirname+'路径').then(定义成功的回调,定义失败的回调) //解决回调地狱调用示例 操作完数据之后return 读取第二个读取文件函数的调用 这样才能继续then //注意当第一个文件读取失败后 后续的代码将不会执行 因为在封装的时候如果err后return不是p 而是对失败函数的调用 可以使用.catch方法捕获所有then的错误 readFilePromise(__dirname+'路径1') .then(function(data1){ console.log(data1) return readFilePromise(__dirname+'路径2') }).then(function(data2){ console.log(data2) return readFilePromise(__dirname+'路径3') }).then(function(data3){ console.log(data3) }).catch(function(err){ console.log(err.message) }) ``` - 当后续的Promise执行需要严格依赖前面的Promise的结果,此时只能使用catch捕获错误(第一个Promise发生错误 后续不在执行) - 如果前面的Promise执行失败后,应该让后续的Promise正常去掉用,此时只能使用then来指定失败的回调(不影响后续的then的正常执行,失败的Promise的下一个then的成功回调中数据将是undefined) - 疑问: - Promise这个构造函数内部是如何拿到这个resolve和reject的 - 有Promise执行失败后 指定的失败回调函数中并没有返回一个Promise实例 为什么可以继续调用then, 而且还进入了这个then的成功回调中(显然上一次的是失败的,也并没有返回这次的promise实例) ## ES6和ES7的一些高级语法 - let const - 箭头函数 - Promise - 解构赋值 - 默认形参 - Object.assign(obj1,obj2,obj3) es6 合并对象 - 函数扩展 function test(...arg) var arr = [1,2,3] test(...arr) - 模板字符串 `${name}` - 字符串的扩展 .startsWith .endsWith padStart padEnd includes - async await - ES6中的导入和导出 import 变量名 from '标识符' export default {} export - 定义对象的快捷方式 键和值一样的时候写一个即可, 对象中的方法可以简写成 方法名(){} ``` var a =10 { a, show(){} } ``` - class 关键字 - Fetch API ## render函数 ``` var vue = new Vue({ render(createElements){ return createElements(组件) }//可以简写成render:c=>c(组件) }) ``` > 实例化vue的时候render会调用,并且传递一个createElements的方法 你可以在render函数内部调用这个createElements方法并传递一个组件,页面会渲染这个组件,el选中的元素内容将被这个组件覆盖并只能放这一个组件 ## vue模板文件 默认使用import导入的vue 只支持使用.vue模板文件来定义组件(可以更改vue包的模块载入配置) 但是官方推荐使用.vue模板文件的方式 - 文件内容: ```vue
模板内容