npm install -g @vue/cli // 安装vue-cli 3.0
vue create name // 创建项目
模式配置
Vue CLI v3.0.0-beta.15
? Please pick a preset:
default (babel,eslint) // 默认
> Manually select features // 自定义模式
插件安装配置
Vue CLI v3.0.0-beta.15
? Please pick a preset: Manually select features // 之前选择的自定义模式
? Check the features needed for your project:
(*) Babel // Babel编译
( ) TypeScript
( ) Projectressive Web App (PWA) Support
(*) Router // 路由
(*) Vuex // 状态管理器
(*) CSS Pre-processors // CSS预处理器
(*) Linter / Formatter // 代码检测和格式化
( ) Unit Testing // 以及单元测试
( ) E2E Testing // 暂时不考虑端到端测试(E2E Testing)
css预处理语言
此处选择 LESS
Vue CLI v3.0.0-beta.15
? Please pick a preset: Manually select features // 之前选择的自定义模式
? Check the features needed for your project:
Babel,Router,Vuex,CSS Pre-processors,Linter / Formatter,Unit Testing
?Pick a Css pre-processor (PostCss,Autoprefixer and CSS Modules are supported by default):
SCSS / SASS
> LESS
Stylus
ESLint的代码规范
此处使用 Standard代码规范
Vue CLI v3.0.0-beta.15
? Please pick a preset: Manually select features // 之前选择的自定义模式
? Check the features needed for your project:
Babel,Router,Vuex,CSS Pre-processors,Linter / Formatter,Unit Testing
?Pick a Css pre-processor (PostCss,Autoprefixer and CSS Modules are supported by default):LESS
? Pick a linter / formatter config:
> ESLint with error prevention only
ESLint + Airbnb config
ESLint + Standard config
ESLint + Prettier
何时进行代码检测
此处选择在保存时进行检测
Vue CLI v3.0.0-beta.15
? Please pick a preset: Manually select features // 之前选择的自定义模式
? Check the features needed for your project:
Babel,Router,Vuex,CSS Pre-processors,Linter / Formatter,Unit Testing
?Pick a Css pre-processor (PostCss,Autoprefixer and CSS Modules are supported by default):LESS
? Pick a linter / formatter config: Standard
? Pick additional lint features:
> (*) Lint on save
( ) Lint and fix on commit
单元测试解决方案
此处选择 Jest
Vue CLI v3.0.0-beta.15
? Please pick a preset: Manually select features // 之前选择的自定义模式
? Check the features needed for your project:
Babel,Router,Vuex,CSS Pre-processors,Linter / Formatter,Unit Testing
?Pick a Css pre-processor (PostCss,Autoprefixer and CSS Modules are supported by default):LESS
? Pick a linter / formatter config: Standard
? Pick additional lint features: Lint on save
? Pick a unit testing soution:
Mocha + chai
> Jest
配置文件存放位置
此处选择单独保存在各自的配置文件中
Vue CLI v3.0.0-beta.15
? Please pick a preset: Manually select features // 之前选择的自定义模式
? Check the features needed for your project:
Babel,Router,Vuex,CSS Pre-processors,Linter / Formatter,Unit Testing
?Pick a Css pre-processor (PostCss,Autoprefixer and CSS Modules are supported by default):LESS
? Pick a linter / formatter config: Standard
? Pick additional lint features: Lint on save
? Pick a unit testing soution: Jest
? Where do you prefer placing config for Babel,PostCSS,ESLint,etc.?
> In dedicated config files
In package.json
cli-3.0总共提供了四种方式来制定环境变量:
.env
文件,配置所有情况下都会用到的配置(不知道这个存在的意义,所有的都需要的也就不需要配置了吧)。.env.local
文件,配置所有情况下都会用到的配置,与.env
的区别是只会在本地,该文件不会被git跟踪。.env.[mode]
文件,配置对应某个模式下的配置,比如:.env.development来配置开发环境的配置。.env.[mode].local
文件,配置对应某个模式下的配置,与.env.[mode]
的区别也只是会在本地生效,该文件不会被git跟踪。在文件中,我们只需要以key=value的方式就可以设置变量了。
//例如
FOO=bar
VUE_APP_SECRET=secret
设置完环境变量之后就可以在我们的项目中使用这两个变量了。
不过还需要注意的是在项目的不同地方使用,限制也不一样。
console.log(process.env.VUE_APP_SECRET)
模式是Vue CLI项目中的一个重要概念。默认情况下,Vue CLI项目中有三种模式:
vue-cli-service serve
下,即开发环境使用vue-cli-service build
和vue-cli-service test:e2e
下,即正式环境使用vue-cli-service test:unit
下使用另外,如果你想要修改模式下默认的环境变量的话可以通过–mode来实现,例如:
"dev-build": "vue-cli-service build --mode development"
// .env.local
VUE_APP_SECRET=''
// .env.development
VUE_APP_SECRET=''
// .env.online
VUE_APP_SECRET=''
// package.json
"serve": "vue-cli-service serve",
"local": "vue-cli-service build --mode local",
"build": "vue-cli-service build --mode online",
"lint": "vue-cli-service lint"
// vue.config.js
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://xxxx/device/', //对应自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': '' // 请求接口以/api开头
}
}
}
}
}
// package.json 允许任何域名访问
"serve": "vue-cli-service serve --host 0.0.0.0"
const path = require('path')
const resolve = dir => {
return path.join(__dirname, dir)
}
module.exports = {
/** 区分打包环境与开发环境
* process.env.NODE_ENV==='production' (打包环境)
* process.env.NODE_ENV==='development' (开发环境)
* baseUrl: process.env.NODE_ENV==='production'?"https://cdn.didabisai.com/front/":'front/',
*/
// 项目部署的基础路径
// 我们默认假设你的应用将会部署在域名的根部,
// 例如 https://www.my-app.com/
// 如果你的应用部署在一个子路径下,那么你需要在这里
// 指定子路径。比如将你的应用部署在
// https://www.foobar.com/my-app/
// 那么将这个值改为 '/my-app/'
// publicPath:'', // 二级目录名称
outputDir: "dist", // 打包文件夹名称
// 不检测语法
lintOnSave: false, // 使用带有浏览器内编译器的完整构建版本 // https://vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only
runtimeCompiler: false, // babel-loader默认会跳过`node_modules`依赖. // 通过这个选项可以显示转译一个依赖
transpileDependencies: [
/* string or regex */
], // 是否为生产环境构建生成sourceMap?
productionSourceMap: false, // 调整内部的webpack配置. // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
// 快捷配置
chainWebpack: config => {
config.resolve.alias
.set('@', resolve('src'))
// 导入直接 @images
.set('@images', resolve('src/assets/images'))
// 图片获取路径 src="@images/login/logo.png"
},
configureWebpack: () => {}, // CSS 相关选项
css: {
// 将组件内部的css提取到一个单独的css文件(只用在生产环境)
// 也可以是传递给 extract-text-webpack-plugin 的选项对象
extract: true, // 允许生成 CSS source maps?
sourceMap: false, // pass custom options to pre-processor loaders. e.g. to pass options to // sass-loader, use { sass: { ... } }
loaderOptions: {}, // Enable CSS modules for all css / pre-processor files. // This option does not affect *.vue files.
modules: false
}, // use thread-loader for babel & TS in production build // enabled by default if the machine has more than 1 cores
pwa: {}, // configure webpack-dev-server behavior
devServer: {
open: process.platform === "darwin",
disableHostCheck: false,
host: "0.0.0.0",
port: 8080,
https: false,
hotOnly: false, // See https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#configuring-proxy
proxy: {
'/api': {
target: 'http://xxx.xx.x.x:7788/',
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': '/'
}
}
}
// before: app => {}
},
// 第三方插件配置
pluginOptions: {
// ...
}
}
// api
import request from '@/tools/request/request'
export function test(params) {
return request.post(
'ews2/add'
)
}
// service/common/serverAddr
let localServerAddr = '/api/' //本地服务器地址
//let localServerAddr = 'http://x.x.x.x/' //预上线地址
// let LongServerAddr = 'https://xx.xx-info.xx/' //远程服务器地址
// 服务器地址
function getAddr(){
// 本地使用指定服务器
if(
/http:\/\/localhost/ig.test(window.location.href)
|| /192.168.8.76/ig.test(window.location.href)
){
return localServerAddr
}
return `${window.location.protocol}//${window.location.host}/`
}
export default getAddr()
src
// 接口文件夹
-api
// 静态文件 (img、css、js、其他)
-assets
// 全局公共组件
-components
// 全局过滤文件
-filter
// 本地存储
-localStorageService
-key // 本地值名称
-localStorageService // 本地存储方法
// 路由文件
-router
-routes // 所有路由地址
-index // 路由配置
// 同级组件传值使用
-sameLeve
//... 自己定义文件
// 系统服务文件
-service
// 配置信息
-common
-serverAddr // 获取服务器地址前缀
-variable // 配置vue全局使用数据
// 外部使用方法与定义数据文件
-data
// vuex
-store
-modules // 定义的模块vuex
-mutationFn_name // 定义vuex的名称
// 工具
-tools
-regular // 方法处理封装
-request // 请求封装
-weChat // 微信调用方法封装
// iview框架方法封装
-vuxUI
-base // 封装部分弹层方法
npm i axios // 安装插件
import axios from 'axios';
import Cookies from 'js-cookie'
import serverAddr from '@/service/common/serverAddr'
let instance = axios.create({
baseURL: serverAddr, // 地址 ,需要用时切换相应的地址
timeout: 3000, // 请求超时
})
// post请求头的设置
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
// 添加请求拦截器
instance.interceptors.request.use(
config=>{
// 在发送请求之前做些什么
let token = Cookies.get('token')
token && (config.headers.token = token)
return config;
},
error=> {
// 对请求错误做些什么
return Promise.reject(error);
}
)
// 添加响应拦截器
instance.interceptors.response.use(
response=> {
// 对响应数据做点什么
// console.log(response.data.msg)
if(response.data.code === 0){
return Promise.resolve(response)
}else{
return Promise.reject(response)
}
},
error=>{
// 对响应错误做点什么
const responseCode = error.response.status
switch (responseCode) {
// 401:未登录
case 401:
break
// 404请求不存在
case 404:
// 弹窗
alert('网络请求不存在')
break
default:
alert(error.response.data.message)
}
return Promise.reject(error)
}
)
/**
* 使用es6中的类,进行简单封装
*/
class request {
get(url, params) {
return new Promise((resolve, reject) =>{
instance.get(url,{params})
.then(result=>resolve(result))
.catch(err=>reject(err))
})
}
post(url, params) {
return new Promise((resolve, reject) =>{
instance.post(url,params)
.then(result=>resolve(result))
.catch(err=>reject(err))
})
}
}
export default request;
import { isIframe } from '@/tools/regular/regular'
/***
* 数组数据去重
* @param arr
* @return {Array}
*/
function removeArr( arr ){
let temp = {};
let newArr = [];
for(let i=0;i<arr.length;i++ ){
if( !temp[arr[i]] ){
temp[arr[i]]= true;
newArr.push( arr[i] );
}
}
return newArr;
}
class localStorageService {
constructor(){
let keyArr = window.localStorage.getItem('keyArr')
if(keyArr){
this.arr = removeArr(JSON.parse(keyArr))
}else{
this.arr = []
window.localStorage.setItem('keyArr',JSON.stringify(this.arr))
}
}
/***
* 启动清理器
*/
startClear(){
// console.log(this.arr)
this.cleanBeOverdue()
}
/**
* 清除过期本地存储
*/
cleanBeOverdue() {
//不存在本地存储,继续轮询
// console.log(this.arr)
if(this.arr.length===0){
return false
}
let nowTime = (new Date()).getTime();
for (let i=0;i<this.arr.length;i++){
let key = this.arr[i]
let item = window.localStorage.getItem(key)
item = JSON.parse(item)
// 存在时间
if(typeof item === 'Object' && item.time){
//删除到期本地存储
if(nowTime*1 >= item.time*1){
this.remove(key)
}
}
}
setTimeout(()=>{
this.cleanBeOverdue()
},1000)
}
/**
* 设置本地存储
* @param key 键名
* @param value 值
* @param time 存储时间 (毫秒)
*/
set(key,value,time=1000*60*60*24*7){
let futureTime = (new Date()).getTime()*1 + time; //到期时间
let data = {
data:value,
time:futureTime
};
data = JSON.stringify(data);
window.localStorage.setItem(key,data)
// 存储本地
this.arr.push(key)
window.localStorage.setItem('keyArr',JSON.stringify(removeArr(this.arr)))
}
/**
* 获取本地存储
* @param key 键名
*/
get(key){
let getValue = window.localStorage.getItem(key);
return getValue==null?null:JSON.parse(getValue).data;
}
/**
* 获取iframe父级本地存储
* @param key 键名
*/
getParent(key){
if(!isIframe()) return null // 不在iframe里
let getValue = parent.localStorage.getItem(key);
return getValue==null?null:JSON.parse(getValue).data;
}
/**
* 删除某个存储
* @param key 键名
*/
remove(key){
window.localStorage.removeItem(key)
for (let i = 0;i< this.arr.length;i++){
let item = this.arr[i]
if(String(item) === String(key) ){
this.arr.splice(i,1)
}
}
window.localStorage.setItem('keyArr',JSON.stringify(this.arr))
}
/**
* 删除所有存储
*/
clearAll(){
window.localStorage.clear()
}
}
export default new localStorageService();
import { USER_INFO } from '@/localStorageService/key'
import localStorageService from '@/localStorageService/localStorageService'
const config = {
install(Vue, options) {
/**
* 图片地址
* @param url
* @return {string}
*/
Vue.prototype.$imgUrl = url=>'/api'+url
/**
* 获取用户信息
*/
Vue.prototype.$userInfo = ()=>localStorageService.get(USER_INFO)
}
}
export default config
import Vue from 'vue'
Vue.filter('comVal', val=>{
return val?val:'-'
})
npm i -S vuex
npm i -S vuex-persistedstate # 对数据进行缓存
// vuex/index
import Vue from 'vue'
import Vuex from 'vuex'
//”vuex”:”^3.0.1”,运用”vuex-persistedstate”来对数据进行缓存
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)
const module = {
// data 存储数据
state: {},
//过滤 filter
getters: {},
// 操控 state 里面的数据的 methods
mutations: {},
// 调用 mutations 里的方法,可以进行异步操作
actions:{},
// 数据进行缓存
plugins: [createPersistedState()]
}
export default new Vuex.Store(module)
import store from './vuex/index'
Vue.config.productionTip = false;
new Vue({
el: '#app',
router,
store, //使用store
// 传递一个参数: 让页面默认显示的模板 return
render: h => h(App)
})
定义规则
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// data 存储数据
const state = {
age: [
{name: '1', age: 1},
{name: '2', age: 2},
{name: '3', age: 3},
{name: '4', age: 4}
],
name: 'abc',
vxcart: []
}
// 相当于 computed 作用于 state 过滤操作 .....
const getters = {
guolv (state) {
state.name = '123'
}
}
// 主要是用来操控 state 里面的数据的
const mutations = {
addage () {
state.age++
},
minusage () {
state.age--
},
vxaddCart (state, value) {
state.vxcart.push(value)
},
vxjian (state, value) {
state.vxcart.forEach((val, index) => {
if (val.title === value.title) {
state.vxcart.splice(index, 1)
}
})
}
}
// 来调用 mutations 里的方法,可以进行异步操作
// 通过actions进行commit提交给mutation,再进行数据操作 , 例如发送请求
const actions = {
// 默认接收了一个参数
addagepro ({commit},value) {
//参数使用mutations的里面的函数
// addage是里面的参数,value需要存储的值
commit('addage',value) //调用mutations里的addage函数
}
}
// 语法检测的时候 new必须进行赋值
/* eslint-disable no-new */
export default new Vuex.Store({
// 是用来保存数据的
state,
mutations,
actions,
getters
})
使用方法
<template>
<div id="app">
{{ $store.state }}
<button @click="addage()">+button>
<button @click="minusage()">-button>
<router-view :aa="aaaa">router-view>
{{age}}
div>
template>
<script>
// 接收的参数的格式 map+驼峰命令
// state = mapState
import {mapState, mapMutations, mapActions, mapGetters} from 'vuex'
import header from './components/hreder.vue'
export default {
name: 'app',
computed: {
//解构state 相当于把里面的name、age放在data里,可以直接用
...mapState([
'name',
'age'
]),
...mapGetters([
//...
])
},
methods: {
//接收 mutations
...mapMutations([
//接收里面的方法有哪些
'addage',
'minusage'
]),
getState(){
//获取state的状态 只可以读,不可改
console.log(this.$store.state)
//修改state状态 key ,value
this.$store.commit('name',{name: 'kuke_kuke'})
}
}
}
script>
/*
dispatch:含有异步操作,例如向后台提交数据,写法: this.$store.dispatch('mutations方法名',值)
commit:同步操作,写法:this.$store.commit('mutations方法名',值)
*/
this.$store.commit('toShowLoginDialog', true);
this.$store.dispatch('toShowLoginDialog',false)
定义规则
// vuex/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import market from "./modules/market/market";
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
market
}
}
)
//vuex/modules/mutationFn_name.js 设置调起变量函数名称
import { SET_MARKET_COUNT } from "../mutationFn_name";
import { getMarketingCount } from '@/api/market/market';//接口
export default {
namespaced: true,
state: {
count: 0
},
actions: {
getMarketingCount({commit}, params) {
return new Promise((resolve, reject) => {
getMarketingCount(params,{loading:{auto:false}})
.then(resp=>{
let data = resp.body;
commit(SET_MARKET_COUNT, data.marketingCount)
})
.catch(e=>console.log(e));
})
}
},
mutations: {
[SET_MARKET_COUNT](state, data) {
state.count = data
}
},
getters: {
getMarketCount: state => {
return state.count
},
}
}
调用方法
// App.vue 调起函数
getMark_num(){
let userInfo = localStorageService.getObj(SR_USER_INFO);
// userInfo = '13533282209'; // local
userInfo = '13926264396'; //demo
let params = {
account:userInfo,
calc_date:'2018002'
};
// market下的getMarketingCount函数
this.$store.dispatch('market/getMarketingCount',params);
// 不开启命名空间 ,直接写 actions 下的userLogin函数名
this.$store.dispatch('userLogin', param);
}
调用完方法后,同级组件数值发生变化
// 其他.vue
import {mapActions, mapGetters} from 'vuex'
computed: {
mark_num() {
const marketCount = this.getMarketCount();
return marketCount;
}
},
methods: {
// 显示的数据
...mapGetters({
// 函数名 getMarketCount
getMarketCount: 'market/getMarketCount', //调起 marke下getMarketCount函数
})
}
npm i vue-router
// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import iView from 'iview';
// vuex获取本地存储
import store from '@/store/index.js'
// 路由模版
import article from './routes/article';
import user from './routes/user';
Vue.use(Router)
let RouterFn = new Router({
routes:routersArr()
})
// 全局路由钩子函数 对全局有效
RouterFn.beforeEach((to, from, next) => {
let auth = to.meta.auth;//路由页面进入权限
let token = store.getters['user/getToken']; // 判断是否登陆
// console.log(token)
if (auth) {
// 需要登录才有权限进入
if(token){
// 已经登录 继续走
next()
}else{
// 未登录
iView.Message.warning({
content:'该页面需要登录才能进入'
})
}
} else {
// 不需要权限的页面
next()
}
})
export default RouterFn;
function routersArr() {
let routes = article
.concat(user)
;
return routes
}
// router/routes/article.js
export default [
{
path:'/articleNote',
name:'articleNote',
// 路由meta传参
meta:{
auth:true,// 需要登录才能进入
hideFooter:true
},
component:()=>import('../../views/Article/ArticleNote.vue'),
},
]
import Vue from 'vue'
import App from './App.vue'
// 导入路由
import router from './router/index'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
const router = new Router({
routes: [
{path: '/', component: index},
{
path: '/a',
component: a,
children: [// 子路由
{path: 'aaa', component: aa},
{path: ':id', component: aa},
/*
以“/”开头的嵌套路径会被当作根路径,所以子路由上不用加“/”;在生成路由时,主路由上的path会被自动添加到子路由之前,所以子路由上的path不用在重新声明主路由上的path了。
*/
{
path: 'collection',
name: 'Collection',
component: Collection
},
]
},
// /b/ bb
{path: '/b/:id', name: 'b',omponent: b},
]
})
属性:to 、replace、 append、 tag、 active-class、 exact 、 event、 exact-active-class
to (必选参数): url
<router-link to="home">Homerouter-link>
<router-link :to="{ path: '/home' }">Homerouter-link>
tag 把 渲染成某种标签,例如
<router-link
:to="'index'"
tag="li"
>Homerouter-link>
exact 严格模式
<li><router-link to="/" exact>严格匹配router-link>li>
active-class 链接激活时的样式
<template>
<router-link to="/about" active-class="activeClass" >aboutrouter-link>
template>
<style>
.router-link-active{
color:red;
}
styles>
一、标签传参
<router-link :to="{ name:'b',query:{ id:123 } }">/b/bbrouter-link>
<router-link :to="{ path:'/b/bb',params:{ id:123 } }">/b/bbrouter-link>
二、路由方法传参
// 路由跳转跳转
this.$router.push({
path:'/path', //路径
name:'pathName', //配置路由时的name
// 传参params
params:{
title:'title',
info:'info'
},
// 传参query
query : {
title:'title',
info:'info'
}
})
create(){
console.log(this.$route.query)
console.log(this.$route.params)
}
this.$router.go(-1) // 返回上一页
this.$router.back() // 返回上一页
this.$router.go(1) // 前进一页
const router = new Router({
routes: [
{path: '/', component: index},
// 1.直接写想要跳转到的网址
{path: '/d', redirect: 'http://baidu.com',meta :{}},
// 2.根据name跳转
{path: '/e', redirect: {name: 'c'}},
// 3.定义函数
{path: '/f',
redirect: (hash, params, query) => {
// hash 网址信息
// params/query 接收路由参数
if (hash.query.id === 123456) {
return {name: 'c'}
} else {
return '/a'
}
//最后必须return 返回一个路由路径
}},
]
})
判断是否登陆,有无进入页面权限。 具体参考2.7.2 路由模块化
const router = new Router({
routes: [
{path: '/', component: index},
{
path: '/g',
component: g,
// 触发的事件 访问这个网址之后 加载模板之前
beforeEnter (to, from, next) {
// to 到哪里去
// from 从哪里来
// next 是否继续往下加载模板
next() //继续往下加载模板
}
}
]
})
export default {
// 模板加载之前执行
beforeRouteEnter (to, from, next) {
// to 到哪里去
// from 从哪里来
// next 是否继续往下加载模板
next() //继续往下加载模板
}
}
export default {
// 监听路由获取参数
watch: {
'$route'(newValue, oldValue) {
}
}
}
//在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
beforeCreate
//实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
created
//在挂载开始之前被调用:相关的 render 函数首次被调用。
beforeMount
//el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
mounted
//数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
beforeUpdate
// 路由离开当前页面
beforeRouteLeave
//由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
updated
//实例销毁之前调用。在这一步,实例仍然完全可用。
beforeDestroy
//Vue 实例销毁后调用
destroyed
<div id='app'>
<button @click='but($event)'>button>
div>
<script>
new Vue({
el: "#app",
data: {
news: [ {name: '1',age:12} ,{name: '2',age:12},{name: '3'},{name: '4'}]
},
methods:{
but(event){
console.log(event)
event.target.style.background = 'red';
}
}
})
script>
<template>
<p>{{ text }}p>
template>
<script>
export default{
name:'child', // 组件名称
data(){
return {
text:'我是子组件'
}
},
methods(){
// 追加文字
addText(){
this.text += '2'
}
}
}
script>
<template>
<child>child>
template>
<script>
import child from 'xxx/child.vue' // 导入子组件
export default{
methods(){},
components:{
child // 导入子组件到页面模版
}
}
script>
定义子组件接收参数
<template>
<div>
<p>{{ text }}p>
<p>{{ getText }}p>
div>
template>
<script>
export default{
props:{
// 接收父组件参数
getText:{ // getText 参数名称
type:String, // 参数类型
required:false,// 是否必须
default:'我是默认值' // 默认值
}
},
name:'child', // 组件名称
data(){
return {
text:'我是子组件'
}
},
methods(){
// 追加文字
addText(){
this.text += '2'
}
}
}
script>
<template>
<child
:getText='我是传入的参数'
>child>
template>
<script>
import child from 'xxx/child.vue' // 导入子组件
export default{
methods(){},
components:{
child // 导入子组件到页面模版
}
}
script>
<template>
<button @click='back'>传值button>
template>
<script>
export default{
name:'child', // 组件名称
methods(){
// 传父组件值
back(){
/*
参数1:接收值的方法名称
参数2:传递的参数
*/
this.$emit('backParent','我是传给父组件的值')
}
}
}
script>
<template>
<child
@backParent='getVal'
>child>
template>
<script>
import child from 'xxx/child.vue' // 导入子组件
export default{
methods(){
// 接收子组件传值的方法
getVal(val){
console.log(val) // 我是传给父组件的值
}
},
components:{
child // 导入子组件到页面模版
}
}
script>
<template>
<p>{{ text }}p>
template>
<script>
export default{
name:'child', // 组件名称
data(){
return {
text:'我是子组件'
}
},
methods(){
// 追加文字
addText(){
this.text += '2'
}
}
}
script>
<template>
<div>
<child ref='childElement'>child>
<button @click='clickChild'>调用子组件方法button>
div>
template>
<script>
import child from 'xxx/child.vue' // 导入子组件
export default{
methods(){
// 调用子组件方法
clickChild(){
// 获取子组件
let childElement = this.$refs.childElement
// 调用子组件下的方法
childElement.addText()
// 获取子组件下的参数值
console.log(childElement.text) // 我是子组件
}
},
components:{
child // 导入子组件到页面模版
}
}
script>
<template>
<div>
<child >child>
<p>{{ num }}p>
div>
template>
<script>
import child from 'xxx/child.vue' // 导入子组件
export default{
data(){
return {
num:0
}
},
methods(){
numAdd(){
num += 1
}
},
components:{
child // 导入子组件到页面模版
}
}
script>
<template>
<button @click='clickParentAdd'>调用子组件方法button>
template>
<script>
export default{
name:'child', // 组件名称
methods(){
// 追加父组件值
clickParentAdd(){
console.log(this.$parent) // 获取到父组件
// 调用父组件方法
this.$parent.numAdd()
}
}
}
script>
1.定义源文件
src
-sameLeve
-headerTitle // 随便定义名称
// sameLeve\headerTitle.js
import Vue from 'vue'
export default new Vue
2.同级组件
<header/>
<content/>
3.header组件传值
import headerTitle from '@/sameLeve/headerTitle'
// ...
methods:{
// 定义传参函数
getIframe(){
headerTitle.$emit('headerTitle',123)
}
}
4.content组件监听值
import headerTitle from '@/sameLeve/headerTitle'
// ....
mounted(){
// 初始化监听值
headerTitle.$on('headerTitle',title=> {
console.log(title) // 123
})
},
App.vue
<template>
<div id="app">
<router-view v-if="isRouterAlive" >router-view>
div>
template>
<script>
export default {
name: 'App',
data () {
return {
isRouterAlive: true
}
},
provide () { //父组件中通过provide来提供变量,在子组件中通过inject来注入变量。
return {
reload: this.reload
}
},
methods: {
// 刷新页面
reload () {
this.isRouterAlive = false
this.$nextTick(()=>{
this.isRouterAlive = true
})
}
},
}
script>
其他.vue页面调用
export default {
inject:['reload'],
methods:{
click(){
this.reload(); // 刷新页面
}
}
}
元素是vue 里面的一个内置组件
在里面使用 v-bind: is,可以实现动态组件的效果
<template>
<components is='a' />
template>
<script>
import a from '@/components/a'
import b from '@/components/a'
export default {
components:{
a,
b
}
}
script>
假如父组件需要在子组件内放一些DOM,那么这些DOM是显示、不显示、在哪个地方显示、如何显示,就是slot分发负责的活。
<template>
<div>
<child>
<p>插入子组件的内容p>
child>
div>
template>
<script>
// 引入子组件...
script>
<template>
<div>
<p>默认显示p>
<slot>slot>
div>
template>
<template>
<div>
<child>
<p slot='name1'>我是name1p>
<p slot='name2'>我是name2p>
<p slot='name3'>我是name3p>
child>
div>
template>
<script>
// 引入子组件...
script>
<template>
<div>
<p>默认显示p>
<slot name='name1'>slot>
<slot name='name2'>slot>
<slot name='name3'>slot>
div>
template>
过渡动画要在使用 if 或 show 时才能实现过渡效果
<style>
/* 开始为绿颜色 */
p{
color:green;
}
/* .slow 为动画名+状态 */
/* 动画开始状态到正常显示的过渡, 正常状态到结束状态的过渡 */
.show-enter-active,.show-leave-active{
transition: color 3s
}
/* 动画初始状态,正常状态到结束状态的过渡 */
.show-enter,.show-leave-active{
color:red;
}
style>
<body>
<div id="app">
<button @click="show = !show">按钮button>
<transition name="show">
<p v-if="show">p标签p>
transition>
div>
<script>
new Vue({
el: '#app',
data: {
show: true
}
})
script>
<style>
.abc-enter-active{
animation: d 3s
}
.abc-leave-active{
animation: d 3s
}
@keyframes d{
0%{ transform:scale(0) }
50%{ transform:scale(2) }
100%{ transform:scale(1) }
}
style>
<body>
<div id="app">
<button @click="show = !show">按钮button>
<transition name="abc">
<div v-if="show">dsadas div>
transition>
div>
<script>
new Vue({
el: '#app',
data: {
show: true
}
})
script>
<div id="app">
<div
v-changeColor="{ color:'red' }"
>div>
div>
<script>
// 自定义组件名称changeColor
Vue.directive('changeColor',(el,bind)=>{
console.log(el);// 绑定的元素
console.log(bind.value); // 传过来的数据 { color:'red' }
// 标签样式变化
el.style.color = bind.value.color;
});
new Vue({
el: '#app',
data: {}
})
script>
<div id="app">
<div v-changeColor="'asdas'">ddddiv>
div>
<script>
new Vue({
el: '#app',
directives: {
// 自定义组件名称 changeColor
changeColor: {
// 当我们绑定的时候触发 只触发一次
bind(){
console.log('自定义组件绑定')
},
// 主方法
inserted(el){
console.log(el); // 绑定的元素
el.style.color = 'red'
},
// 绑定的数据改变的时触发
update(){},
// 组件完成一次更新的时候触发
componentUpdated(){ },
// 和元素解除绑定的时候触发
unbind(){}
}
}
})
script>
有些时候我们会遇到数据更新了,但发现视图没有更新,下面说明如何解决
// 方案一:利用Vue.set(object,key,val) -- 全局
Vue.set(vm.obj,'k1','v1')
// 方案二:利用this.$set(this.obj,key,val) --- 局部
this.$set(this.obj,'k1','v1')
// 方案三:利用Object.assign({},this.obj)创建新对象
this.obj = Object.assign({}, this.obj,{'k1','v1'})
openReaonly (item) {
item.readonly = true
// index item当前位置的index
// 1 删除 本身
// 插入新数据,修改后的item
this.conArr.splice(index, 1, item)
}
cnpm i echarts
<template>
<div id="rejectEchart">div>
template>
<script>
import echarts from 'echarts'
// 数据源
import { rejectEchartData } from '../data/rejectEchart'
export default {
name: 'rejectEchart',
mounted(){
this.rejectEchart = this.$refs.rejectEchart
},
methods: {
init () {
this.charts = echarts.init(this.rejectEchart)
this.charts.setOption(rejectEchartData)
}
},
}
script>
let option = {
title : {
text: '某站点用户访问来源',
subtext: '纯属虚构',
x:'center'
},
// ...
}
let option = {
toolbox: {
feature: {
saveAsImage: {} // 保存图片
}
},
// ...
}
let option = {
series: [{
//...
label:{
normal: {
show: true,
position: 'top'
}
}
}]
// ...
}
legend: {
// pie-实心圆 emptycircle-空闲圆
type: 'pie', // 图标
data:['临停车','月租车','免费车','储值车','军警车'],
left:'center',
bottom:'10%',
itemWidth:10,//图例的宽度
itemHeight:10,//图例的高度
textStyle:{//图例文字的样式
color:'#ccc',
fontSize:16
}
},
series: [
{
name: "温度",//鼠标放在折线点上显示的名称
type: "line",//折线图
symbol: 'circle',//折线点设置为实心点
symbolSize: 4, //折线点的大小
itemStyle: {
normal: {
color: "#386db3",//折线点的颜色
lineStyle: {
color: "#386db3"//折线的颜色
}
}
},
lineStyle:{
normal:{
width:100 // 线宽
}
}
]
xAxis: [{
gridIndex: 0,,c
type: "category",
data: xdata,
axisLine: {
lineStyle:{
color:'#272729',//x轴的颜色
width:8,//轴线的宽度
}
},
}],
yAxis: [
axisLine: {
lineStyle:{
color:'#272729',// y轴的颜色
width:8,//y轴线的宽度
}
}],
axisLabel: {
show: true,
textStyle: {
color: '#fff'
}
}
yAxis: {
splitLine: {show: false},
}
部分echart转载
原文链接:https://blog.csdn.net/zhumizhumi/article/details/81537765
cnpm i js-cookie
import Cookies from 'js-cookie'
Cookies.set('token','token')
Cookies.get('token','token')
cnpm i -S blueimp-md5
导入:import md5 from 'blueimp-md5'
普通加密:let val=md5('value');
cnpm i vue-easytable
使用
// 引入样式
import 'vue-easytable/libs/themes-base/index.css'
// 导入 table 和 分页组件
import {VTable,VPagination} from 'vue-easytable'
// 注册到全局
Vue.component(VTable.name, VTable)
Vue.component(VPagination.name, VPagination)
cnpm i qs
import qs from 'qs'
qs.stringify(params)
cnpm i qrcodejs2
<template>
<div id="qrcode">div>
template>
<script>
import QRCode from 'qrcodejs2'
export default {
name: 'comQrcode',
components:{ QRCode },
methods: {
// 创建二维码
createCode ({
url,
width=500,
height=500,
colorDark="#000",
colorLight="#fff",
}) {
document.getElementById("qrcode").innerHTML = ""
new QRCode('qrcode', {
width: width,
height: height,
text: url, // 二维码地址
colorDark : colorDark,
colorLight : colorLight,
})
}
},
}
script>
<style scoped>
style>
h是组件返回的 这个是vnode作用域实在 h所在的组件 你可以把h改成 this.$createElement
render: (h, params) => {
let create = this.$createElement // 这个
return create(dataAutoComplete, {
key: 'part_' + params.index,
ref: 'partSelector',
props: {
pagename: 'part_baseselect',
param: {}
},
on: {
'on-select': (data) => {
console.log(this.$refs)
}
}
})
// 跳转描点
goAnchor(domId) {
this.$el.querySelector(`#${domId}`).scrollIntoView()
}