VUE
入门
安装
-
CDN引入
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
-
下载和引入
开发环境 https://vuejs.org/js/vue.js
生产环境 https://vue.org/js/vue.min.js
-
npm安装
案例
-
hellow,world
<div id="app"> <h2>{{message}}</h2> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: 'hello,vue.js' } }) </script>
注意:1.new Vuew({})的V要大写
-
v-for
<body> <div id="app"> <ul> <li v-for="item in movies"> {{item}} </li> </ul> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { movies: ['闻香是女人', '盗梦空间', ' 霸王别姬'] } }) </script> </body>
-
计数器
<body> <div id="app"> <h2>当前数字为:{{count}}</h2> <button @click="decrement">-</button> <button @click="increment">+</button> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { count: 0 }, methods: { decrement() { this.count-- }, increment() { this.count++ } } }) </script> </body>
模板语法
-
常见指令
-
v-once:只渲染一次
<h2 v-once>{{message}}</h2>
-
v-html:渲染html片段
<h2 v-html="url"></h2>
-
v-text:渲染数据,但是不够灵活,只能渲染数据里面的内容
<h2 v-text="url"></h2>
-
v-cloak:当Vue对象创建前存在这个属性,创建后这个属性消失,可以用来动态显示样式
<style> [v-cloak] { display: none; } </style> <div id="app"> <h2 v-cloak>{{message}}</h2> </div>
setTimeout(function () { var vm = new Vue({ el: '#app', data: { message: 'hahah' }, methods: {} }); }, 2000)
-
v-bind用于绑定属性
<img v-bind:src="..." />
语法糖写法 <img:src="…" alt="" >
-
v-bind动态绑定class
对象语法
<div v-bind:class="{key:value1,key2:value2}"> </div> <div v-bind:class="{类名:boolean}"> </div> <div v-bind:class="{active:isActive,line:isLine}"> {{message}} </div>
-
v-bind动态绑定style
对象语法
<p v-bind:style="{color:pColor,fontSize:finalFS +'px'}">阿拉善凯迪拉克函数</p>
-
computed计算属性
computed: { fullName: function () { return this.firstName + ' ' + this.laseName; } },
computed是计算属性,在使用的使用直接使用变量名,如{{fullName}}
注意:computed是有缓存的,第一次调用执行函数体,以后调用不执行函数体。
computed setter与getter
computed: { fullName: { set: function (newValue) { this.firstName = newValue.split(' ')[0]; this.lastName = newValue.split(' ')[1]; console.log("1111"); }, get: function () { return this.firstName + ' ' + this.lastName } } },
-
v-on
在事件定义是,写方法时省略了小括号,但是方法本身是需要一个参数的,这个时候Vue会默认将浏览器生产的event事件对象作为参数传入到方法
<button @click="btnClick"></button> btnClick(event) { console.log(event) }
当既需要传递参数又需要传递事件时,可以使用$envent
<button @click="btn2Click('abc',$event)"></button>
-
v-on修饰符
@click.stop 阻止冒泡
@click.prevent 阻止默认行为
@click.native -监听组件根元素的原生事件
@click.once - 只触发一次回调
-
v-if v-else-if v-else
<div id="app"> <div v-if="isUser"> <label for="account">账号登录</label> <input id="account" type="text" placeholder="账号" key="account"> </div> <div v-else> <label for="email">邮箱登录</label> <input id="email" type="text" placeholder="邮箱" key="email"> </div> <button @click="isUser = !isUser">切换登录方式</button> </div>
key的作用是区别相同元素
-
v-show 与 v-if
v-show为false是,该元素增加display:none属性
v-if为false时,不存在对应dom元素
所以显示与隐藏之间切换频繁用v-show,否则用v-if
-
v-for 遍历对象
<ul> <li v-for="(value,key) in person">{{value}}{{key}}</li> </ul> <!-- person: { name: "gzh", age: 29, }-->
-
Vue.set(this.letters,0,‘bb’)
参数1,要修改的数组
参数2,索引值
参数3,修改后的值
//响应式数组方法 // 1. pop // 2.push // 3.shift // 4.unshift // 5.splice // 6.split // 7.sort // 8.reverse // 9.Vue.set(this.letter, 0, 'c') // 10.Vue.delete() //不能响应的方法 // this.letter[0] = 'b'
-
filters
传入属性,对属性进行改造
<h2>{{book.price | finalPrice}}</h2>
filters: { finalPrice(price) { return "¥" + price.toFixed(2); } }
-
v-model
实现表单的双向绑定
<input type="text" v-model="message">
radio
<label for="male"> <input type="radio" id="male" value="man" v-model="sex">男 </label> <label for="frame"> <input type="radio" id="frame" value="woman" v-model="sex">女 </label>
checkbox
单选情况
<label for="agree"><input type="checkbox" id="agree" v-model="isAgree"> 同意</label>
多选情况
<input type="checkbox" id="" value="篮球" v-model="hobbies">篮球 <input type="checkbox" id="" value="羽毛球" v-model="hobbies">羽毛球 <input type="checkbox" id="" value="足球" v-model="hobbies">足球 <input type="checkbox" id="" value="乒乓球" v-model="hobbies">兵乓球
isAgree: false, hobbies: []
select
单选情况
<select id="" v-model="fruit"> <option value="苹果">苹果</option> <option value="青枣">青枣</option> <option value="葡萄">葡萄</option> <option value="榴莲">榴莲</option> </select>
多选情况
<select id="" v-model="fruits" multiple> <option value="苹果">苹果</option> <option value="青枣">青枣</option> <option value="葡萄">葡萄</option> <option value="榴莲">榴莲</option> </select>
修饰符
lazy
当失去焦点或者按回车才会引起data的变化
-
商城项目
项目准备
- 划分目录结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uz0PZUtp-1585295018729)(…/images/catalog.png)]
-
在App.vue导入base.css和normalize.css文件初始化样式
-
配置vue.config.js,设置路径别名
module.exports = { configureWebpack: { resolve: { alias: { 'assets': '@/assets', 'components': '@/components', 'pages': '@/pages', 'server': '@/server', 'common': '@/common' } } } };
-
将项目进行模块划分:tabbar->路由映射关系
项目开发
-
导航栏开发
-
轮播图开发
注意,在A组件中引用B组件,A组件的name不能和导入B组件的名字一样,否则会导致内存泄露;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5IhJZ7ru-1585295018730)(…/images/navbartips.png)]
-
推荐组件
-
货物列表
使用better-scroll使滚动更加顺滑
npm install better-scroll
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZfitlYPQ-1585295018730)(…/images/betterscroll.png)]
在vue中不能在ceated中初始化better-scroll,应在mounted中
//监听滚动 this.bscroll.on("scroll", position => { this.$emit("scroll", position); }); //监听上拉更新,当数据异步加载完成需要调用refresh刷新scroll this.bscroll.on("pullingUp", () => { this.$emit("pullingUp"); });
更多详细用法请查看better-scroll官网。
-
事件总线,派发监听事件和响应事件
-
在vue原型prototype中添加
Vue.prototype.$bus = new Vue();
-
被监听者
this.$bus.$emit("imageLoadFinish");
-
监听者
this.$bus.$on("imageLoadFinish", () => { //... });
-
取消
this.$bus.$off("全局事件","当前函数")
-
-
防抖函数
防止refresh多次调用。
debounce(func, delay) { let timer = null; return function(...args) { //判断是否有定时器,如果有清除掉定时器. timer && clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); }, delay); }; }
-
吸顶效果
-
获取组件的offsetTop
this.$ref.tabControl.$el.offsetTop
-
-
mixin混入,将不同组件相同逻辑的代码放到一个mixin的方法里。
-
this.$nextTick(()=>()),当数据和dom全部渲染完会调用。
用在标题滚动到内容
-
安装自定义插件
-
在main.js注册
Vue.use(toast);
-
新建一个js文件
import Toast from './Toast.vue'; const toastObj = {}; toastObj.install = function (Vue) { // 1. 创建组件构造器 const toastConstructor = Vue.extend(Toast); // 2. 使用new 创建一个组件对象 const toastComp = new toastConstructor(); // 3. 将组件对象挂载到dom元素上 toastComp.$mount(document.createElement('div')); // 4. toast.$el对应的div document.body.appendChild(toastComp.$el); // 5. 将对象挂载到Vue prototype上 Vue.prototype.$toast = toastComp; }; export default toastObj;
-
使用
this.$toast.show("您未选中商品");
-
fastClick解决300ms延迟
npm install fastclick
在main.js照片那个使用 fastclick.attach(document.body)
-
使用vue-lazyload实现图片懒加载
npm install vue-lazyload
在main.js使用
Vue.use(VueLazyLoad,{ loading:require("占位符图片"); });
将
:src
改为v-lazy
-
移动端适配
postcss-px-to-viewport
插件改变css单位px为vmnpm install postcss-px-to-view --save-dev
创建postcss.config.js
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J44zM0RX-1585295018731)(…/images/px2vw.png)]
vue面试题
-
vue的响应式原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tMbhlO1I-1585295018732)(…/images/vueprototype.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hLIDmNRE-1585295018732)(…/images/vuethory.png)]
-
采用
Object.defineProperty(object,key,{get(){},set(newValue){}})
来监测属性值的改变 -
采用订阅发布者模式来通知视图的更新
// 发布者 class Dep { constructor() { this.subs = []; } addSubs(watcher) { this.subs.push(watcher); } notify() { this.subs.forEach(item => { item.update(); }); } remove(watcher) { this.subs = this.subs.fitler(item => item === watcher); } } // 订阅者 class Watcher { constructor(name) { this.name = name; } update() { console.log(this.name + "发生改变,可以更新视图了"); } } // 模拟data对象 const obj = { name: "gzh", age: 18 }; Object.keys(obj).forEach((key) => { let value = obj[key]; //一个属性新增一个dep对象 let dep = new Dep(); Object.defineProperty(obj, key, { set(newValue) { if (value === newValue) return; value = newValue; dep.notify(); }, get() { const watcher = new Watcher(value); dep.addSubs(watcher); return value; } }); });