css预处理使用
一、stylus
1、安装依赖
npm install stylus stylus-loader --save-dev
2、vue项目中使用
(1)vue 文件中使用 style 标签中加 lang="stylus" 在styl 文件中使用
<style scoped lang="stylus">
a {
color: #42b983;
}
width = 500px
.my
background yellow
width width
height (@width/2)
margin-left (@width + @height)
</style>
(2)style 标签中加 lang="stylus" 在style内部通过@import ‘../assets/base.styl’ 的方式导入stylus文件
<style scoped lang="stylus">
@import '../assets/stylus/helloWord.styl'
</style>
(3) 通过js 导入 也可以全局main.js 中通过import ‘../assets/base.styl’
import Vue from 'vue'
import App from './App'
import router from './router'
import './assets/stylus/base.styl'
Vue.config.productionTip = false
console.log(Vue)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
(4)可以在组件script标签中使用
<script>
import '../assets/stylus/base.styl'
export default {
name: 'HelloWorld',
data () {
return {
msg: 'app'
}
}
}
</script>
二、less
在vue-cli项目中安装依赖
npm install less less-loader --save
style 标签中加 lang="less"
<style scoped lang="less">
@import '../assets/less/base.less';
@width: 100px;
.my{
width: @width;
height: 200px;
p{
color: red;
}
}
三、在vue-cli 项目中使用sass
在vue-cli项目中安装依赖
npm install node-sass sass-loader --save-dev
style 标签中加 lang="scss"
<style scoped lang="scss">
@import '../assets/scss/base.scss';
$width:200px;
.my{
width: $width;
height: 100px;
color: red;
background: pink;
}
</style>
三者相同点
1、在vue-cli 项目中不需要配置webpack loader
2、需要注意安装版本问题,版本过高导致loader不可使用
不同点
1、stylus可以在组件script标签中使用,也可以在main.js中全局使用 2、scss 和 less 都不能直接在script标签中使用, 但scss提供了全局引用的方法 使用 sass-resources-loader 的方法, less无
图片使用和css背景图
1、模版中img加载图片的常见方法
(1)直接image src引入图片路径
<img src="/../static/food/03.jpg">
// 或者
<img src="@/../static/food/03.jpg">
(2)使用require 加载 img 通过v-bind 绑定图片资源(:src)
<template>
<div class="hello">
<img :src="img">
</div>
</template>
<script>
export default {
name: 'ScssTest',
data () {
return {
img: require('@/../static/food/01.jpg'),
img: require('@/assets/food/01.jpg'),
}
}
}
</script>
(3) 使用import加载图片img 通过v-bind 绑定图片资源(:src)
<template>
<div class="hello">
<img :src="img_2">
</div>
</template>
<script>
import foodImg from '@/../static/food/02.jpg'
export default {
name: 'ScssTest',
data () {
return {
img_2: foodImg
}
}
}
</script>
设置css背景图
(1)通过绑定style属性设置背景图样式
<template>
<div class="hello">
<div class="bgtp" :style="{backgroundImage: 'url(' + img_2 + ')'}"></div>
<div class="bgtp" :style="{backgroundImage: 'url(' + img + ')'}"></div>
</div>
</template>
<script>
import foodImg from '@/../static/food/02.jpg'
export default {
name: 'ScssTest',
data () {
return {
img: require('@/../static/food/01.jpg'),
img_2: foodImg
}
}
}
</script>
(2)直接书写css样式,注意路径
<style scoped lang="scss">
$width:200px;
.my{
width: $width;
height: 100px;
color: red;
background: url('/static/food/04.jpg');
}
</style>
axios 使用
1、安装axios
npm install axios
2、新建axios 实例创建request.js
import axios from 'axios'
let myAxios = axios.create({
baseURL: 'https://ccapi.csslcloud.net',
timeout: 10000,
headers: {'token': 'foobar'}
})
export function getRoomDes (data) {
return myAxios({
method: 'post',
url: '/api/room/room_desc',
data: data,
})
}
export default myAxios
3、在vue 组件中使用
import { getRoomDes } from '../api/request.js'
export default {
name: 'ScssTest',
data () {
return {
}
},
created() {
getRoomDes({roomid: 'E9B9F3137F42855D9C33DC5901307461'}).then((response) => {
console.log(response, '++++++')
}).catch((err) => {
console.log(err, '++++++')
})
},
}
</script>
4、在main.js 中给Vue原型链赋值,修改方法名,在组件中使用
// main.js
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
// 引入axios 实例
import myAxios from './api/request.js'
// 挂载在Vue 实例
Vue.prototype.$ajax = myAxios
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
// vue组件中
export default {
name: 'ScssTest',
data () {
},
created() {
// 使用方法
this.$ajax({
method: 'get',
url: '/api/room/room_desc',
params: {roomid: 'E9B9F3137F42855D9C33DC5901307461'},
}).then((response) => {
console.log(response, '++++++')
}).catch((err) => {
console.log(err, '++++++')
})
},
}
</script>
mockjs 使用
1、安装mock.js
npm install mockjs --save
2、新建mock/mock.js 文件
import Mock from 'mockjs'
let data = {
name:1,
id:2
}
// 监听方法
Mock.mock('https://ccapi.csslcloud.net/api/room/room_desc', data)
//或
Mock.mock('https://ccapi.csslcloud.net/api/room/room_desc', 'get', data)
// 或
Mock.mock('https://ccapi.csslcloud.net/api/room/room_desc', 'post', () => {
return data
})
使用post请求,url 为字符串即可,使用get 请求,需要使用正则匹配url
3、在main.js 中引入mock/mock.js (不需要mock 的时候注释即可)
import Vue from 'vue'
import App from './App'
import router from './router'
import myAxios from './api/request.js'
// 引入自定义mock文件
import './mock/mock.js'
Vue.config.productionTip = false
Vue.prototype.$ajax = myAxios
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
eslint 的使用
1、在使用vue-cli 创建项目的时候选择使用eslint
2、给之前的vue项目新增eslint (1)安装依赖
通过npm直接安装或将依赖写入package.json 通过npm install 安装
"babel-eslint": "^8.2.1",
"eslint": "^4.15.0",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.0.0"
(2)新建.eslintrc.js(或将新建的带eslint 的文件copy)
// https://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint'
},
env: {
browser: true,
},
extends: [
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
'plugin:vue/essential',
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
'standard'
],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}
}
(3)新增.eslintignore 忽略文件
build/*.js
config/*.js
src/assets
(4)修改webpack 配置
build\webpack.base.conf.js:
// 新增
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
entry: {
},
output: {
},
resolve: {
},
externals: {
},
module: {
rules: [
// 新增
...(config.dev.useEslint ? [createLintingRule()] : [])
],
loaders: [
]
},
plugins: [
]
}
config\index.js:
module.exports = {
dev: {
// Use Eslint Loader?
// If true, your code will be linted during bundling and
// linting errors and warnings will be shown in the console.
useEslint: true,
// If true, eslint errors and warnings will also be shown in the error overlay
// in the browser.
showEslintErrorsInOverlay: false,
},
build: {
}
}
- 运行 npm run lint 可以查看到所有不符合规范的代码
- 运行 npm run lint --fix,可以快速修复所有不符合规范的代码
- 也可以写成 "lint": "eslint --ext .js,.vue src/api/index.js --fix",然后直接运行 npm run lint 进行修复
3、编辑器配置vscode 安装并配置完成 ESLint 后,文件 > 首选项 > 设置 打开 VSCode 配置文件,添加如下配置
{
"eslint.enable": false, // 是否开启检测
"eslint.validate": [
"javascript",
"javascriptreact",
// "vue-html",
// "html",
// "vue",
{
"language": "vue-html",
"autoFix": false // 编辑vue-html,保存时是否根据eslint规则自动修复
},
{
"language": "html",
"autoFix": false
},
{
"language": "vue",
"autoFix": false
}
],
"eslint.run": "onSave",
"eslint.autoFixOnSave": false, // 保存时是否根据eslint规则自动修复
}
vue router 使用
安装使用
1:下载 npm i vue-router -S
2:在main.js中引入 import VueRouter from 'vue-router';
3:安装插件Vue.use(VueRouter);
4:创建路由对象并配置路由规则
let router = new VueRouter({routes:[{path:'/home',component:Home}]});
5:将其路由对象传递给Vue的实例,options中加入 router:router
6:在app.vue中留坑
//main.js文件中引入
import Vue from 'vue';
import VueRouter from 'vue-router';
//主体
import App from './components/app.vue';
import Home from './components/home.vue'
//安装插件
Vue.use(VueRouter); //挂载属性
//创建路由对象并配置路由规则
let router = new VueRouter({
routes: [
//一个个对象
{ path: '/home', component: Home }
]
});
//new Vue 启动
new Vue({
el: '#app',
//让vue知道我们的路由规则
router: router, //可以简写router
render: c => c(App),
})
最后记得在在app.vue中“留坑”
//app.vue中
<template>
<div>
<!-- 留坑,非常重要 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
data(){
return {}
}
}
</script>
漏由转调方式及传参
router-link 声明式导航
// 字符串路径
<router-link to="/test">xxxxxxxx</router-link>
// v-bind 绑定to
// data 中的数据
<router-link :to="lessTest">ca s ca s ca s c</router-link>
// 对象name
<router-link :to="{name: 'ScssTest'}">ca s ca s ca s c</router-link>
// 对象path
<router-link :to="{path: '/test'}">ca s ca s ca s c</router-link>
// 对象带其他参数
<router-link :to="{path: '/test', params:{a:1}}">ca s ca s ca s c</router-link>
js编程式导航
// 参数:可以是一个字符串,也可以是一个描述地址的对象或数字
1) this.$router.push('/hello'): 相当于点击路由链接(可以返回到当前路由界面) 队列的方式(先进先出)
2) this.$router.replace({name: 'hello'}, params:{a:1}):
this.$router.replace({path: '/hello', query:{c:1}}):用新路由替换当前路由(不可以返回到当前路由界面) ==>> 栈的方式(先进后出)
3) this.$router.back(): 请求(返回)上一个记录路由
4) this.$router.go(-1): 请求(返回)上一个记录路由
5) this.$router.go(1): 请求下一个记录路由
query 传参与 params 传参区别
query 使用name 或者 path 引入 问号带参数/test?a=1 刷新后参数不丢失
this.$router.push({name: 'test', query: {a:1}})
this.$router.push({path: '/test', query: {a:1}})
params传参需要在漏油上配置参数(否则,刷新后参数会丢失),最好用name引入,使用path引入时,需要将参数写在路径上且不用写params,路径显示为 /test/1
let router = new VueRouter({
routes: [
//一个个对象
{
path: '/test/:a',
component: Test,
name:'test'
}
]
});
this.$router.push({name: 'test', params: {a:1}})
this.$router.push({path: `/test/1`})
嵌套漏油
1、父路由组件增加router-view
<template>
<div class="hello">
<router-view></router-view>
<img src="/../static/food/03.jpg">
<div class="bgtp" :style="{backgroundImage: 'url(' + img + ')'}"></div>
</div>
</template>
2、引入子路由文件
注意:子路由路径前不能加‘/ ’,否则匹配全局路径
import Vue from 'vue'
import Router from 'vue-router'
import ScssTest from '@/components/scssTest'
import Content from '@/components/Content'
import Detail from '@/components/Detail'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/test/:a',
name: 'ScssTest',
component: ScssTest,
children: [
{
path: 'content',
component: Content
},
{
path: 'detail',
component: Detail
}
]
}
]
})
3、子路由跳转方式
// content -- detail
this.$router.push('detail')
//或者
this.$router.push('/test/1/detail')
router-link 方法 同上
路由懒加载
import Detail from '@/components/Detail'
//改写为:
const Detail = () => import('@/components/Detail')
路由重定向
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' }
]
})
const router = new VueRouter({
routes: [
{ path: '/a', redirect: { name: 'foo' }}
]
})
const router = new VueRouter({
routes: [
{ path: '/a', redirect: to => {
// 方法接收 目标路由 作为参数
// return 重定向的 字符串路径/路径对象
}}
]
})
路由守卫
1、全局守卫
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
let router = new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
// 前置守卫to, from, next(必须执行)
router.beforeEach((to, from, next) => {
// ...
console.log(to, from, next, '+++++before+++++')
next()
})
// 后置守卫
router.afterEach((to, from) => {
// ...
console.log(to, from, '+++++after+++++')
})
export default router
2、路由独享守卫
// 参数和全局守卫一样
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
3、组件内守卫
export default {
name: 'Content',
data () {
return {
}
},
created () {
setTimeout(() => {
this.$router.push({path: 'detail'})
}, 3000)
},
destroyed () {
console.log('++++++++++++++')
},
beforeRouteEnter: function (to, from, next) {
console.log('+++beforeRouteEnter+++')
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
next()
},
beforeRouteUpdate: function (to, from, next) {
console.log('+++beforeRouteUpdate+++')
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
next()
},
beforeRouteLeave: function (to, from, next) {
console.log('+++++beforeRouteLeave+++++')
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
next()
}
}
完整的导航解析流程
导航被触发。
在失活的组件里调用离开守卫。
调用全局的 beforeEach 守卫。
在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
在路由配置里调用 beforeEnter。
解析异步路由组件。
在被激活的组件里调用 beforeRouteEnter。
调用全局的 beforeResolve 守卫 (2.5+)。
导航被确认。
调用全局的 afterEach 钩子。
触发 DOM 更新。
用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
vuex的使用
安装vuex
npm install vuex -S
初始化vuex
1、新建文件src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 数据
const state = {
name: 'lxb',
status: true,
data: [],
nums: {}
}
const store = new Vuex.Store({
state
})
export default store
2、main.js引入store
import Vue from 'vue'
import App from './App'
import router from './router'
import myAxios from './api/request.js'
Vue.config.productionTip = fals
// 引入store
import store from './store'
new Vue({
el: '#app',
store,
components: { App },
template: '<App/>'
})
3、使用store中的数据
可以在组件中获取到this.$store.state.name
组件中模版使用state 数据
<template>
<div class="hello">
<h5>{{name}}</h5>
</div>
</template>
<script>
export default {
name: 'ScssTest',
data () {
return {
msg: 'app'
}
},
created () {
console.log(this.$store.state, '+++this.$store.state+++++')
},
computed: {
name (newValue, oldValue) {
return this.$store.state.name
}
}
}
</script>
mapState
1、引入mapState
2、在computed使用mapState方法
<template>
<div class="hello">
<h5>{{name}}</h5>
</div>
</template>
<script>
// 引入mapState
import { mapState } from 'vuex'
export default {
name: 'ScssTest',
data () {
return {
msg: 'app'
}
},
created () {
console.log(this.$store.state, '+++this.$store.state+++++')
},
computed: {
// name (newValue, oldValue) {
// return this.$store.state.name
// },
// map辅助函数最简写法
...mapState(['name'])
}
//或者
// map辅助函数常见的3种写法
computed:mapState({
// name: 'name' 直接写法
// name: state => state.name
// 如果要使用this,不能使用箭头函数
name (state) {
return `${this.msg}_${state.name}`
}
})
}
</script>
getter
可以对state中的数据进行处理后使用,相当于computed,当有多个组件都需要对state中的某个数据进行相同处理时,使用getters比较方便
1、新建getters对象
2、在store中使用getters
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 数据
const state = {
name: 'lxb',
status: true,
data: [1, 2, 3, 4, 5],
nums: {}
}
// getters
const getters = {
oddData (state) {
return state.data.filter(num => num % 2 === 0)
}
}
const store = new Vuex.Store({
state,
getters
})
export default store
3、在组件中使用getters
<template>
<div class="less">
<p v-for="item in oddData" :key="item">{{ item }}</p>
</div>
</template>
<script>
export default {
name: 'LessTest',
data () {
return {
}
},
computed: {
oddData () {
return this.$store.getters.oddData
}
}
}
</script>
mapGetters
1、引入mapGetters 辅助函数
2、在组件中使用
<template>
<div class="less">
<p v-for="item in myOddData" :key="item">{{ item }}</p>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'LessTest',
data () {
return {
msg: 'liang xin bo'
}
},
computed: {
// 不改变名字参数为数组
// ...mapGetters(['oddData'])
// 改变名字参数为对象
...mapGetters({
myOddData: 'oddData'
})
}
}
</script>
mutations
1、只有mutations 中的方法可以修改state的值
2、只能用来做同步修改,不可异步调用
引入mutations
1、在store/index.js 新增mutations 对象 2、新建mutations 中修改state 的方法
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 数据
const state = {
name: 'lxb',
status: true,
data: [1, 2, 3, 4, 5],
nums: {}
}
// getters
const getters = {
oddData (state) {
return state.data.filter(num => num % 2 === 0)
}
}
// 修改state的值
const mutations = {
changeName: (state, newValue) => {
state.name = newValue.name
}
}
const store = new Vuex.Store({
state,
getters,
mutations
})
export default store
3、在组件中通过this.$store.commit 方法提交
<template>
<div class="hello">
<h5>{{name}}</h5>
<button @click="changeName">改变名字</button>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'ScssTest',
data () {
return {
msg: 'app'
}
},
created () {
},
methods: {
changeName () {
let name = Math.random() * 100
// 通过以下两种方法提交修改state
// this.$store.commit('changeName', name)
this.$store.commit({type: 'changeName', name})
}
},
computed: {
// map辅助函数
...mapState({
// name: 'name' 直接写法
// name: state => state.name
// 如果要使用this,不能使用箭头函数
name (state) {
return `${this.msg}_${state.name}`
}
})
}
}
</script>
mapMutations
1、可以简化提交方法,将自定义方法映射为需要使用的commit方法
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}
actions
1、用来在异步操作下提交mutations
引入actions
1、store/index.js加入actions
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 数据
const state = {
name: 'lxb',
status: true,
data: [1, 2, 3, 4, 5],
nums: {}
}
// getters
const getters = {
oddData (state) {
return state.data.filter(num => num % 2 === 0)
}
}
// 修改state的值
const mutations = {
changeName: (state, newValue) => {
console.log(newValue)
state.name = newValue
}
}
// 提交mutations
const actions = {
changeName: (context, item) => {
console.log('++11111++')
setTimeout(() => {
context.commit('changeName', item)
console.log('++22222++')
}, 1000)
}
}
const store = new Vuex.Store({
state,
getters,
mutations,
actions
})
export default store
2、在组件中通过dispatch提交actions
<template>
<div class="hello">
<h5>{{name}}</h5>
<button @click="changeMyName">改变名字</button>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
name: 'ScssTest',
data () {
return {
msg: 'app',
},
created () {
methods: {
changeMyName () {
let name = Math.random() * 100
// actions
this.$store.dispatch('changeName', name).then((data) => {
console.log(data, '++++++this.$store.dispatchchangeName+++++=')
})
},
},
computed: {
// name (newValue, oldValue) {
// return this.$store.state.name
// },
// map辅助函数
...mapState({
// name: 'name' 直接写法
// name: state => state.name
// 如果要使用this,不能使用箭头函数
name (state) {
return `${this.msg}_${state.name}`
}
})
}
}
</script>
mapActions
1、可以简化提交方法,将自定义方法映射为需要提交的dispatch方法
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
安装vuedevtool避坑指南(旧版,已失效)
1、从 github.com/vuejs/vue-d… 下载安装包(master分支!!!!!)
2、npm install
3、npm run build
4、从扩展程序安装即可
新版
1、从 github.com/vuejs/vue-d… 下载安装包(main分支!!!!!)
2、npm install/ yarn install
3、npm run build
4、从扩展程序安装即可(找到packages/shell-chrome 拖到扩展程序即可安装)
vue更新数据视图不更新解决办法
// 1、使用this.$set()
this.$set(this.lists, 0, {value:1})
// 2、数据修改完成后,使用this.$forceUpdate() 强制更新视图
this.$forceUpdate()
vue 还原data 数据
// this.$data 包含现有的data数据,
// this.$options.data() 中是原有的data数据
// 还原全部数据
Object.assign(this.$data, this.$options.data())
// 还原部分数据
Object.assign(this.$data.searchForm, this.$options.data().searchForm)