004--自找麻烦之 vue2.0
人的差异其实很小:一,你在犹豫,他在做,所以他比你成功机会多;二,你在找借口,他在解决问题,所以他比你事业有成;三,你在消费,他在理财,所以他比你更富足;四,你在算计自己的利益,他在考虑对方的利益,所以他比你更加有人脉。成功没有奇迹,只有轨迹!1. Vuex:用于各个组件的数据共享2. Nuxt.js : 基于vue的服务端渲染应用框架3. 任何一门框架的学习最好的资料就是官方文档 ...
人的差异其实很小:一,你在犹豫,他在做,所以他比你成功机会多;二,你在找借口,他在解决问题,所以他比你事业有成;三,你在消费,他在理财,所以他比你更富足;四,你在算计自己的利益,他在考虑对方的利益,所以他比你更加有人脉。成功没有奇迹,只有轨迹!
1. Vuex:用于各个组件的数据共享
2. Nuxt.js : 基于vue的服务端渲染应用框架
3. 任何一门框架的学习最好的资料就是官方文档
4. vue 不支持IE8以下的浏览器(记住)
5. 要在外面取vue实例app里面的data要用: app.$data
6. 学习vue只需要操作数据,不会再涉及到DOM的操作
7. vue的双向数据绑定原理(面试会问,重要,以后补充)
8. vue注册全局组件用 component ;子组件接收父组件的数据要用 props
Vue.component("TodoItem",{
props:['content'],
template:"<li>{{content}}</li>"
})
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
9. 子组件传递数据给父组件
10. 生命周期函数就是vue实例在某一个时间点会自动执行的函数
beforeCreate(vue实例进行部分初始化之后会执行);created(完全初始化之后执行);
beforeMount(模板结合vue实例的DOM元素挂载到页面之前执行),mounted(页面挂载之后 执行);
beforeDestroy(组件被销毁之前执行,在控制台调用 vm.$destroy() 时这个函数就执行),destroyed(组件被完全销毁之后执行);
beforeUpdate(当数据发生还没重新渲染之前执行),updated(当数据发生改变重新渲染之后执行)
11. vue指令里面的值不再是字符串,而是js表达式
12. v-text 和 v-html有点类似,区别在于v-text="name"(和 {{name}} 的用法一模一样)做了转义,完整输出内容,而v-html 可以识别html表达式
13. 计算属性 computed(非常重要的特点:内置缓存)的写法(写成函数,返回这个值)
new Vue({
...
computed:{
fullName:function(){
return this.fname + this.lname
}
}
})
<div id="app">{{fullName}}</div>
14. computed 的 get (获取值时执行)和 set(设置值时执行)
new Vue({
...
computed:{
fullName:{
get:function(){
return this.fname + this.lname
},
set:function(value){
var arr = value.split(" ");
this.fname = arr[0];
this.lname = arr[1];
}
}
}
})
15. div绑定某个类名用 :class="{activated: isActivated}" 取决于isActivated是true还是false
:class="[activated]" 这样写activated代表一个变量,变量的内容即是一个类名
16. Vue.set()不光能修改数据,还能添加数据,弥补了Vue数组变异方法的不足; Vue.set()在methods中也可以写成this.$set()
17. vue-cli 的使用
npm i -g vue-cli
vue init webpack Travel (Travel 表示项目放在哪个文件夹下)
基本回车操作,除了一些没见过的选项你不想安装就选择no
cd Travel
npm run dev
18. vue-cli 生成的项目文件分析
package-lock.json package的锁文件(帮助我们确定你安装的第三方包的版本,保持团队编程的统一)
.eslintrc.js 配置了一些代码的规范
.eslintignore 忽略某些文件的检测
.editorconfig 配置了编辑器的语法
static目录 图片,json数据等静态资源
src目录 整个项目的源代码
config目录 项目的配置文件
vue-cli生成的项目中, @ 符号代表 src 目录(这是在build目录中webpack.base.conf.js中帮我们设置好的)
19. 路由就是根据网址的不同,返回不同的内容给用户
20. <router-view></router-view> 显示当前路由地址所对应的内容
21. 单页应用通过js感知url的变化,动态删除再渲染新的DOM结构,把组件内容挂载到页面上,这时候路由是由前端来做的。
22. 单页应用首屏时间慢且SEO差(搜索引擎只认识HTMl当中的内容),多页应用首屏时间快且SEO好
23. 做移动端的页面可以写以下的语句防止用户用手缩放网页
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
24. reset.css 文件:对基础样式的修饰,保证所有浏览器显示的效果基本一致
border.css文件: 为了解决多倍屏1像素边框会被显示成多元素的问题 (1像素边框的解决方案)
npm i fastclick -S : fastclick用来解决移动端click时间300毫秒点击延迟的问题
25. iconfont 阿里巴巴矢量图标库: http://www.iconfont.cn/ (进入图标管理--我的项目--新建项目图标库)
26. 使用stylus: npm i stylus -s ; npm i stylus-loader -s
27. 只对当前组件的样式有效 scoped
<style scoped>
</style>
28. iconfont的使用:选择需要图标加入购物车,添加至项目,下载到本地,再把iconfont.css 和四个字体文件(.eot,.svg,.ttf,.woff)提取出来,将iconfont.css文件中引用字体文件的路径改好就可以用了,
// icon图标库使用 在main.js 中引入 iconfont.css
import 'styles/iconfont.css'
@font-face {font-family: "iconfont"; //这个是iconfont.css文件,修改这里的路径
src: url('./iconfont/iconfont.eot?t=1527149033233'); /* IE9*/
src: url('./iconfont/iconfont.eot?t=1527149033233#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('./iconfont/iconfont.ttf?t=1527149033233') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('./iconfont/iconfont.svg?t=1527149033233#iconfont') format('svg'); /* iOS 4.1- */
}
例如:
<span class="iconfont"></span>
 是一种图标的16进制的字符标识 (可在iconfont的官网查看)
// icon图标库使用 main文件里面要引用
import 'styles/iconfont.css'
29. 在项目的build文件夹中的webpack.base.conf.js中为某些常见的路径配置变量别名,例如'styles':..
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'styles': resolve('src/assets/styles'),
}
}
修改后要重启服务器才不会报错
30. 使用vue-awesome-swiper 来快速构建一个轮播 (新版本有点细节bug,采用老的版本 2.6.7)
github网址:https://github.com/surmon-china/vue-awesome-swiper
npm i vue-awesome-swiper@2.6.7 -s
<template>
<div class="wrapper">
<swiper :options="swiperOption" v-if="showSwiper">
<swiper-slide v-for="item of list" :key="item.id">
<img class="swiper-img" :src="item.imgUrl" />
</swiper-slide>
<div class="swiper-pagination" slot="pagination"></div>
</swiper>
</div>
</template>
data () {
return{
swiperOption: {
pagination: '.swiper-pagination',
loop: true,
autoplay:fasle
}
}
},
:options="swiperOption" 是 这个vue-awesome-swiper 的配置项,pagination是显示圆点,loop是循环播,autoplay是自动轮播
31. 当你要在子组件里面定义一个data的时候,data一定要是一个函数
32. 最好的防止网速太慢轮播图图片没加载完下面的元素抖动的方案 (用vw的话兼容性差)
.wrapper
width: 100%
height: 0
overflow: hidden
padding-bottom: 31.25%
background-color: #eee
33. style用了scoped后样式只对本组件生效,但是有时候又想让某些样式应用于其他组件,所以可以用 >>>
<style lang="stylus" scoped>
.wrapper >>> .swiper-pagination-bullet-active
background: #fff
</style>
34. 谷歌浏览器下载一个插件 Vue.js devtools
35. 对超过div宽度的文字显示成 ... 的CSS写法
overflow: hidden
white-space: nowrap
text-overflow: ellipsis //ellipsis显示省略符号来代表被修剪的文本
显示省略符号来代表被修剪的文本
36. 提到插槽的概念,不懂,后补
37. 数据请求推荐 axios
npm i axios -s
import axios from 'axios' //在需要请求的.vue文件内
axios.get('/api/index.json')
.then(this.getHomeInfoSucc)
methods: {
getDetailinfo () {
axios.get('/api/detail.json?',{
params: {
id: this.$route.params.id // this.$route.params 可以取到当前路由上定义的id参数的值,发get请求带参数就可以这样
}
}).then(this.handleGetDataSucc)
},
38. vue-cli 生成的整个项目只有static目录里面的内容可以被外部访问到
39. vue-cli 生成的项目目录中 配置config文件夹下的index.js文件中的 module.exports
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api':{
target: 'http://localhost:8080',
pathRewrite: {
'^/api':'/static/mock/'
}
}
},
看 proxyTable 配置项,按如上配置 开发环境下的时候请求路径即使写的是 './api' ,它也会帮我们代理到 '/staic/mock'
这个功能是 webpack-dev-server 这个工具提供的
40. 父组件给子组件传值
<home-header :city="city"></home-header>
<script>
export default {
name: 'HomeHeader',
props: {
city: String
}
}
</script>
<div class="header-right">
{{this.city}}
<span class="iconfont arrow-icon"></span>
</div>
41. 页面跳转用 <router-link to='/city'></router-link>
42. 原生app的上下拉动页面效果的插件(到顶部和底部还有弹性的效果) better-scroll 的使用:
https://github.com/ustbhuangyi/better-scroll
npm i better-scroll -s
<div ref="wrapper"> //要类似这种DOM结构,父div里面一个子div,子div里面再写页面的东西
<ul class="content">
<li>...</li>
<li>...</li>
...
</ul>
<!-- you can put some other DOMs here, it won't affect the scrolling -->
</div>
import Bscroll from 'better-scroll'
export default {
name: 'CityList',
mounted () {
this.scroll = new Bscroll(this.$refs.wrapper) //把DOM元素丢进去实例化
}
}
</script>
this.scroll.scrollToElement(element) //这个方法是用来将页面滚动到某个DOM元素的区域的
43. vue2 用 ref 来获取 DOM
<div class="touchscroll" ref='wrapper'></div>
this.$refs.wrapper
44. 兄弟组件之间的传值(兄传值给父,父再传给弟)
methods: { //兄
handleLetterClick (e) {
this.$emit('change',e.target.innerText)
}
}
<city-list :cities="cities" :hot="hotCities" :letter="letter"></city-list> //父
<city-alphabet :cities="cities" @change="handleLetterChange"></city-alphabet>
handleLetterChange (letter) { //父
this.letter = letter
}
props: { //弟
hot: Array,
cities: Object,
letter: String
},
watch: { //弟 注意这一步要在watch里面处理这个传过来的数据
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0]
this.scroll.scrollToElement(element)
}
}
}
45. vue中html元素中不要有逻辑的部分,例如
<li class="search-item border-bottom" v-show="!list.length">没有找到匹配数据</li> //v-show 这里要改在computed 里面
computed: { //改成这样
hasNoData() {
return !this.list.length
}
}
<li class="search-item border-bottom" v-show="hasNoData">没有找到匹配数据</li> // 改成这样
46. Vuex 数据层框架的使用: 就是类似一个仓库,组件共用的数据存放在State里面,外面的组件要改变这个共用数据要通过dispatch方法来调用actions的异步代码调用commit方法来调用Mutations(转变)的同步代码最终mutate(变化)到state里面的数据,外面的组件也可以直接通过Mutations来改变state里面的数据
整个流程: 组件调用action,action调用mutations,Mutations去改变我们的数据
npm i vuex -s
vue-cli生成的项目中在src目录新建一个store文件夹/index.js文件
import Vue from 'vue' // index文件内容
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '北京'
}
})
import store from './store' //mian文件内容
...
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
<div class="header-right">
{{this.$store.state.city}} // 任何组件使用这个store上的共用数据的方法
<span class="iconfont arrow-icon"></span>
</div>
以下是改变共享数据的过程;
methods: { //组件执行这个函数 dispatch方法去调用actions
handerCityClick (city) {
this.$store.dispatch('changeCity',city)
}
},
import Vue from 'vue' //这是store/index文件 actions触发Mutations最终改变state里面的city数据
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '北京'
},
actions: {
changeCity (ctx, city) {
// console.log(city)
ctx.commit('changeCity',city)
}
},
mutations: {
changeCity (state, city) {
state.city = city
}
}
})
47. 编程式导航(路由通过js代码来实现页面路由的跳转了)
methods: {
handerCityClick (city) {
this.$store.commit('changeCity',city)
this.$router.push('/') // 这样就跳转到首页了
}
},
48. localstorage的用法
export default new Vuex.Store({
state: {
city: localStorage.city || '北京'
},
mutations: {
changeCity (state, city) {
state.city = city
localStorage.city = city
}
}
})
更健壮的兼容浏览器的写法(加入try catch 处理某些浏览器关闭本地存储功能代码会报错的问题)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let defaultCity = '汕头'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {}
export default new Vuex.Store({
state: {
city: defaultCity
},
mutations: {
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
}catch (e) {}
}
}
})
谷歌浏览器,右键检查--选择 Application 可以找到 local storage
49. 高级Vuex的api用法
import { mapState } from 'vuex'
export default {
name: 'HomeHeader',
computed: {
...mapState(['city']) // 将state中共享数据映射到本组件的city数据身上
}
}
<div class="header-right">
{{this.city}} //虽然这个city是共享数据,但是映射本组件就可以直接这样用了
</div>
50. 性能优化
<template> // 这个是App.vue 文件
<div id="app">
<keep-alive exclude="Detail"> //用这个标签在前进后退页面的时候就不会重复发送ajax请求,会缓存第一次发送的ajax请求
<router-view/> // exclude="Detail" 表示除了Detail组件不会缓存,其他都会缓存
</keep-alive>
</div>
</template>
activated () { // 重新显示页面比如说城市变了就要重新发送ajax请求就可以写在这个生命周期函数 activated 里面
if (this.lastCity !== this.city) {
this.lastCity = this.city
this.getHomeInfo()
}
}
51. vue中的 <router-link></router-link> 类似 a 标签,但想表示其他标签也可以
<router-link tag='div' to="/" class="header-abs"> // 加上 tag="div" 就可以表示 div 了,同样加上其他就可以表示其他标签
<div class="iconfont header-abs-back"></div>
</router-link>
52. 获取当前页面滚动条的纵坐标位置:
document.documentElement.scrollTop;
53. 对全局事件的解绑
activated () { // 页面展示时执行
window.addEventListener('scroll',this.handleScroll)
},
deactivated () { // 页面切换掉后执行
window.removeEventListener('scroll',this.handleScroll)
}
54. 递归组件的实现(vue中比较难的部分)(组件自己调用自己)
<template>
<div>
<div class="item" v-for="(item,index) of list" :key="index">
<div class="item-title border-bottom">
<span class="item-title-icon"></span>
{{item.title}}
</div>
<div v-if="item.children" class="item-children"> // v-if 与 加上自己子项的类名区分
<detail-list :list="item.children"></detail-list> //用自己的组件名
</div>
</div>
</div>
</template>
<script>
export default {
name: 'DetailList', //组件名
props: {
list: Array
}
}
55. ajax请求要放在 mounted 这个钩子函数里面中请求
56. 解决切换页面时页面滚动到上一个页面的位置的问题(查看官网 -- 滚动行为)
import Vue from 'vue' // 这是router文件夹里面的 index.js 文件
import Router from 'vue-router'
import Home from '@/pages/home/Home'
import City from '@/pages/city/City'
import Detail from '@/pages/detail/Detail'
Vue.use(Router)
export default new Router({
routes: [{
path: '/',
name: 'Home',
component: Home
},{
path: '/city',
name: 'City',
component: City
},
{
path: '/detail/:id',
name: 'Detail',
component: Detail
}],
scrollBehavior (to, from, savedPosition) { //加上这段代码就可以解决
return { x: 0, y: 0}
}
})
57. 修改vue-cli生成的项目的package.json的启动配置项
"scripts": {
"dev": "webpack-dev-server --host 0.0.0.0 --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
},
这样写就能通过ip地址访问webpack-dev启动的服务
58. vue项目的打包上线(针对vue-cli生成的项目)
npm run build 打包编译
把生成的dist目录中的东西给后端,扔到后端的根目录里面就行了
如果要运行在其他路径下
build: { // config文件夹下index.js (vue-cli项目)
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/project/', //修改这里就可以使项目运行在后端的project路径下(当然要重新打包,然后把生成的dist目录修改成project)
59. 项目要请求其他端口或者域名下的接口数据:
module.exports = { // config文件夹下index.js (vue-cli项目)
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api':{
target: 'http://localhost:80', // 前端服务跑在8080端口,后端服务器是80 就改成80就可以了 (其他域名就被整个域名改掉)
pathRewrite: {
'^/api':'/static/mock/' //这里要根据实际情况来改,如果接口本身就是/api 映射到 /api 那就可以把它去掉
}
}
},
60. 行内设置样式
<div class="tiao" :style="{ width: item.jingdu}"></div>
61. router-link 标签上面绑定 @click会失效,要这样绑定 (只要是其他的组件标签都要加.native,原生类似 input这种标签绑定就不用)
<router-link tag="div" to="before" class="wangqi yiyang" @click.native="beforeClick"> // 加上.native
<div :class="{ 'active': !isBenqi }">往期成绩</div>
</router-link>
另外 router-link 标签上的 to='before' 就是把当前路由链接最后一个改成before,如果加上 to='/before' 就是 跳到 /before 的路径下
62. 获取当前页面的路由url地址用 : this.$route.path
63. vue.js 刷新页面 自动执行某个点击事件可以使用vue的生命周期函数,如create或者mounted
64. 在vue中使用 Clipboard.js (页面复制文本到剪切板的)
git地址: https://github.com/zenorocha/clipboard.js
npm install clipboard --save
import Clipboard from 'clipboard' // 引入
export default {
name: 'Recharge',
data () {
return {
clipboard:{},
dizhi: '56565DFlfdgkdflgkdflgkldfgldfgdllfs44544'
}
},
mounted () {
this.clipboard = new Clipboard('.zi') // 绑定要点击的那个按钮
this.clipboard.on('success',function(e){ // 复制成功或者失败的事件
alert("复制成功")
e.clearSelection();
});
this.clipboard.on('error', function(e) {
alert("复制失败!");
});
}
destroyed () {
this.clipboard.destroy() // 要在这里销毁,不然会弹出多次提示
}
}
</script>
<div class="copy">
<div class="zi" data-clipboard-target=".dizhi">一键复制</div> //点击这个按钮,target那个属性是绑定要文本的目标
</div>
<div class="dizhi">{{dizhi}}</div> // 要复制的文本的div
65. vue实现消息的无缝向上滚动效果: 参考 http://www.jb51.net/article/129733.htm (亲测可用)
66. destroyed 这个生命周期表示切换页面后执行,可以在这销毁一些定时器事件等
destroyed () {
window.clearInterval(this.timeID); // 防止切换到其他组件页面报错
},
(setInterval返回值相当于一个Id,每次执行都会产生一个特定的Id,返回值为数字,从一开始逐次累加,清除就是找到他 的id然后 clearInterval(id)就行了)
67. 想要为div加过渡动画就要用transition标签来包裹,vue会自动查看该元素的css来构建动画流程,name属性自定义
<transition name="fade"> // 如果name属性等于fade,那么样式里面的样式名前缀就是.fade-enter,如果不定义name属性,那么样式名前缀就是.v-enter
<div v-if="show">hello world</div>
</transition>
.fade-enter { 隐藏到显示
opacity: 0;
}
.fade-enter-active {
transition: opacity 1s;
}
vue会自动为标签加上这两个类名来做动画,我们只需要定义好类名的样式内容即可
.fade-leave-to{ 显示到隐藏
opacity: 0;
}
.fade-leave-active{
transition: opacity 3s;
}
如果我们想要显示到隐藏与隐藏到显示都有过渡效果,就可以把这些样式写在一起
.fade-enter,.fade-leave-to{
opacity: 0;
}
.fade-enter-active,.fade-leave-active{
transition: opacity 3s;
}
68. vue中使用@keyframe这种css3的动画
@keyframes bounce-in{
0%{
transform: scale(0);
}
50%{
transform: scale(1.5);
}
100%{
transform: scale(1);
}
}
.v-enter-active {
transform-origin: left center;
animation: bounce-in 1s;
}
.v-leave-active{
transform-origin: left center;
animation: bounce-in 1s reverse;
}
69. 在vue中使用animate.css库
<link...> (引入animate.css库)
<transition
name="fade"
enter-active-class="animated swing"
leave-active-class="animated shake"
>
<div v-if="show">hello world</div>
</transition>
70. 加上 appear 和 appear-active-class 页面一刷新就有动画效果产生了(在引入animate库的前提下)
<transition
name="fade"
appear
enter-active-class="animated swing"
leave-active-class="animated shake"
appear-active-class="animated swing"
>
<div v-if="show">hello world</div>
</transition>
71. 插槽的使用(父组件向子组件传递DOM结构数据)
<body>
<div>
<child>
<p slot='header'>header</p> <p slot='footer'>footer</p>
</child>
</div>
<script>
Vue.component('child',{
template: `<div> <slot name='header'></slot> //用这个来接收父组件传递过来的DOM结构
<p>hello</p>
<slot name='footer'></slot> //用这个来接收父组件传递过来的DOM结构
</div>`
})
...
</script>
72. 实现渐隐渐现效果的 vue-cli 中的可复用组件
<template> //例如这个组件名文件名都叫 FadeAnimation
<transition>
<slot></slot>
</transition>
</template>
<script>
export default {
name: 'FadeAnimation'
}
</script>
<style lang="stylus" scoped>
.v-enter,.v-leave-to
opacity: 0
.v-enter-active,.v-leave-active
transition: opacity .5s
</style>
哪个组件要用就引入以上组件然后用组件名包裹要渐隐渐现的元素
<fade-animation>
<common-gallary :imgs="bannerImgs" v-show="showGallary" @close="handleGallaryClose"></common-gallary>
</fade-animation>
73. 项目完成想要真机调试时,使用localhost可以访问,使用内网ip地址访问不了,这是因为webpack-dev启动的项目默认不支持通过ip地址访问
74. 获取url上的?后面的参数用
// 获取期号
let qi = this.$route.query.qi;
console.log(qi)
75. tab 标签页切换时给当前页面的标签添加样式
<router-link tag='div' to='/' class="home" exact> //注意:默认页即首页要加上 exact
<div class="ico">
<span class="iconfont"></span>
</div>
<div class="wenzi">竞猜</div>
</router-link>
<router-link tag='div' to='/my' class="hangqing">
<div class="ico">
<span class="iconfont"> </span>
</div>
<div class="wenzi">我的</div>
</router-link>
在app.vue 中加上
<style>
.router-link-active {
color: #fff //在这里填写你当前标签页的样式
}
</style>
76. Vant库的使用
npm i vant -S , npm i babel-plugin-import -D
在.babelrc中配置
"plugins": [
"transform-vue-jsx",
"transform-runtime",
["import",{"libraryName":"vant","style":true}]
]
src/main.js
import { Button } from 'vant'
Vue.use(Button)
有了这段代码之后,我们就可以在需要的组件页面中加入Button了.
<van-button type="primary">主要按钮</van-button>
如果不在src/main.js里加入代码,而在需要的页面单独引入:
<script>
import { Popup } from 'vant'
export default {
name: 'HomeContent',
components: {
[Popup.name]: Popup
},
<van-popup v-model="show" position="bottom" :overlay="false">
内容
</van-popup>
77. vue使用相对路径打包,可以直接打开(直接本地文件协议可以打开)丢给后台用:
首先需要修改config/index.js文件:
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
// assetsPublicPath: '/transaction/',
assetsPublicPath: './', //修改这里
然后修改build/utils.js文件
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader',
publicPath: '../../', //添加这一行
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
npm run build 即可打包成直接可以访问的文件了
78. 用vue 做語言切換: npm install vue-i18n
import VueI18n from 'vue-i18n' //vue-cli項目的main.js中這麼寫
Vue.use(VueI18n)
import LangEn from '../static/lang/en' // 引入配置的語言包,在static/lang文件夾下
// import LangZhCHS from '../static/lang/zhCHS'
import LangZhCHT from '../static/lang/zhCHT'
import LangYueNan from '../static/lang/yuenan'
const i18n = new VueI18n({
//定义默认语言
locale: 'Cn',
messages:{
'En': LangEn,
'Cn': LangZhCHT,
'Vn': LangYueNan
}
})
new Vue({ // 也是main.js 文件, 要掛載到Vue的實例上
el: '#app',
router,
i18n,
components: { App },
template: '<App/>'
})
在根目录下的static文件夹中新建lang文件夹,作为语言包
//en.js 語言包文件是這樣的
module.exports={
message: {
hello: 'hello',
about: 'about',
welcome: "Welcome"
}
}
//zhCHS.js
module.exports={
message: {
hello: '你好',
about: '关于',
welcome: "欢迎"
}
}
在組件文件里的html上面是這麼用:{{ $t("message.hello") }}
在組件文件里的script裡面是這麼用: this.$t("message.welcome")
动态切换语言这样: this.$i18n.locale='CN'
79. 除了根组件,子组件想定义data必须要把它定义成一个函数
data () {
return {
content: "hello"
}
}
80. vue 显示base64 的图片数据在页面上
<img :src="codeImg" class="img3" />
this.codeImg = "data:image/jpeg;base64,"+ msg.data.img
图片文件是什么格式就这里就写什么格式(png,jpeg等等)
81. vue中异步组件的使用,需要什么才加载什么,提高性能:
import Vue from 'vue' //这是router里面的index.js文件
import Router from 'vue-router'
import Home from '@/pages/home/Home' //这一行删除掉
import My from '@/pages/my/My' //这一行删除掉
import Past from '@/pages/past/Past' //这一行删除掉
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: () => import('@/pages/home/Home') //修改这里
},
{
path: '/goals',
name: 'My',
component: () => import('@/pages/my/My') //修改这里
},
{
path: '/winner',
name: 'Past',
component: () => import('@/pages/past/Past') //修改这里
},
{
path: '/records',
name: 'Shuoming',
component: Shuoming
},
{
path: '/r
异步组件只有在app.js变得特别大(至少超过1mb)的时候才使用,其他情况就不需要考虑使用这种异步组件的形式,但是本人实践中发现有用还是好,首页加载快了很多
以上是在路由中使用异步组件,其他地方也可以用这种形式(父组件包含子组件的地方)
<template>
<div class="bg">
<home-shousuo :duizhanList="duizhanList" :yu_e="yu_e"></home-shousuo>
</div>
</template>
<script>
import HomeShousuo from './components/Shousuo' //这一行去掉
import axios from 'axios'
export default {
name: 'Home',
components: {
HomeShousuo: () => import('./components/Shousuo') //修改这里
},
这个异步组件的方式其实不一定要用,除非app.js真的很大才用,不然反而多了文件请求
更多推荐
所有评论(0)