VUE筆記

準(zhǔn)備工作

一、安裝腳手架

1、安裝vue腳手架,這是構(gòu)建vue項目的工具-g為全局安裝
? npm install -g vue-cli
2、使用webpack打包工具
? vue init webpack my-project
//之后會提示一些信息,全部選擇yes,一直敲回車即可
3、完成之后,進(jìn)入到創(chuàng)建的項目根目錄下
? cd my-project
4、安裝依賴包
? yarn
//說明:yarn是yarn install的簡寫,可直接敲擊yarn,功能和npm install一樣
5、最后運行項目
? yarn run dev
瀏覽器會自動打開運行一個頁面,出現(xiàn)以下頁面,說明成功了。

二、NPM

1、修改npm網(wǎng)址

淘寶 npm 網(wǎng)址
https://npm.taobao.org/
修改
npm config set registry http://registry.npm.taobao.org/
還原
npm config set registry https://registry.npmjs.org/

查看源

npm config get registry
// 或
npm config list
1234

修改源

# 默認(rèn)源
npm config set registry https://registry.npmjs.org

# https -> http,這樣網(wǎng)速就會好很多
npm config set registry http://registry.npmjs.org 

# 如果還不能下載,就切換成淘寶源
npm config set registry https://registry.npm.taobao.org
npm install -g cnpm --registry=https://registry.npm.taobao.org

2、發(fā)布

1、手動創(chuàng)建 package.json或者npm init

{
  "name": "mypridelife",
  "version": "1.0.0",
  "description": "npm of mypridelife",
  "main": "a.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "mypridelife"
  ],
  "author": "mypridelife",
  "license": "ISC"
}

2、創(chuàng)建文件first.js

function hello(){
  console.log("I am the most handsome man. ");
  console.log("Do not accept any rebuttal. ");
}
exports.hello=hello;

3、發(fā)布

npm adduser
npm publish

4、使用

npm install mypridelife

5、創(chuàng)建測試文件test.js

var gyh = require("mypridelife"); 
gyh.hello();

6、運行

node test.js

三、yarn命令列表

常用命令

創(chuàng)建項目:yarn init

安裝依賴包:yarn == yarn install

添加依賴包:yarn add

Yarn命令列表

命令 操作 參數(shù) 標(biāo)簽
yarn add 添加依賴包 包名 --dev/-D
yarn bin 顯示yarn安裝目錄
yarn cache 顯示緩存 列出緩存包:ls,打出緩存目錄路徑:dir,清除緩存:clean
yarn check 檢查包
yarn clean 清理不需要的依賴文件
yarn config 配置 設(shè)置:set <key> <value>, 刪除:delete, 列出:list [-g | --global]
yarn generate-lock-entry 生成鎖定文件
yarn global 全局安裝依賴包 yarn global <add/bin/ls/remove/upgrade> [--prefix] --prefix 包路徑前綴
yarn info 顯示依賴包的信息 包名 --json:json格式顯示結(jié)果
yarn init 互動式創(chuàng)建/更新package.json文件 --yes/-y:以默認(rèn)值生成package.json文件
yarn install 安裝所有依賴包 --flat:只安裝一個版本;--force:強(qiáng)制重新下載安裝;--har:輸出安裝時網(wǎng)絡(luò)性能日志;--no-lockfile:不生成yarn.lock文件;--production:生產(chǎn)模式安裝(不安裝devDependencies中的依賴)
yarn licenses 列出已安裝依賴包的證書 ls:證書列表;generate-disclaimer:生成免責(zé)聲明
yarn link 開發(fā)時鏈接依賴包,以便在其他項目中使用 包名
yarn login 保存你的用戶名、郵箱
yarn logout 刪除你的用戶名、郵箱
yarn list 列出已安裝依賴包 --depth=0:列表深度,從0開始
yarn outdated 檢查過時的依賴包 包名
yarn owner 管理擁有者 ls/add/remove
yarn pack 給包的依賴打包 --filename
yarn publish 將包發(fā)布到npm --tag:版本標(biāo)簽;--access:公開(public)還是限制的(restricted)
yarn remove 卸載包,更新package.json和yarn.lock 包名
yarn run 運行package.json中預(yù)定義的腳本
yarn self-update yarn自身更新--未實現(xiàn)
yarn tag 顯示包的標(biāo)簽 add/rm/ls
yarn team 管理團(tuán)隊 create/destroy/add/rm/ls
yarn test 測試 = yarn run test
yarn unlink 取消鏈接依賴包
yarn upgrade 升級依賴包
yarn version 管理當(dāng)前項目的版本號 --new-version :直接記錄版本號;--no-git-tag-version:不生成git標(biāo)簽
yarn why 分析為什么需要安裝依賴包 包名/包目錄/包目錄中的文件名

四、NPM和Yarn命令對比

npm 命令 Yarn 命令 備注
npm install yarn install 安裝所有依賴包(依據(jù)package.json中的依賴配置參數(shù))
(N/A) yarn install --flat 單版本模式
(N/A) yarn install --har 生成har文件,記錄安裝時網(wǎng)絡(luò)請求性能
(N/A) yarn install --no-lockfile 不讀寫lockfile方式
(N/A) yarn install --pure-lockfile 不生成yarn.lock文件
npm install [package] (N/A) 安裝依賴
npm install --save [package] yarn add [package] 添加生產(chǎn)模式依賴到項目
npm install --save-dev [package] yarn add [package][--dev/-D] 添加開發(fā)模式的依賴
(N/A) yarn add [package][--peer/-P] 對等模式添加依賴,發(fā)布/分享項目時的依賴
npm install --save-optional [package] yarn add [package] [--optional/-O] 添加可選依賴包
npm install --save-exact [package] yarn add [package] [--exact/-E] 精準(zhǔn)添加某版本的包
(N/A) yarn add [package] [--tilde/-T] 添加同一次版本的包,如指定版本為1.2.3,可接受1.2.x的其他版本,但不接受1.3.x的版本
npm install --global [package] yarn global add [package] 添加全局包
npm rebuild yarn install --force 重建
npm uninstall [package] (N/A) 刪除本地依賴包
npm uninstall --save [package] yarn remove [package] 刪除正式依賴包
npm uninstall --save-dev [package] yarn remove [package] 刪除開發(fā)依賴包
npm uninstall --save-optional [package] yarn remove [package] 刪除可選依賴包
npm cache clean yarn cache clean 清除緩存
rm -rf node_modules && npm install yarn upgrade 更新包管理器自身

VUE

一、VUE基礎(chǔ)

1、標(biāo)簽

v-bind:title="message",
v-if="seen"

v-show是初始就加載

v-if 是“真正”的條件渲染,因為它會確保在切換過程中條件塊內(nèi)的事件監(jiān)聽器和子組件適當(dāng)?shù)乇讳N毀和重建。

v-if 也是惰性的:如果在初始渲染時條件為假,則什么也不做——直到條件第一次變?yōu)檎鏁r,才會開始渲染條件塊

v-for="todo in todos"
v-on:click="reverseMessage" v-on  縮寫 @
<input v-model="message">
v-bind:id="dynamicId"     縮寫 :

提升性能:v-pre

  • 說明:vue會跳過這個元素和它的子元素的編譯過程??梢杂脕盹@示原始 Mustache 標(biāo)簽。跳過大量沒有指令的節(jié)點會加快編譯。
<span v-pre>{{ this will not be compiled }}</span>

提升性能:v-once

  • 說明:vue只渲染元素和組件一次。隨后的重新渲染,元素/組件及其所有的子節(jié)點將被視為靜態(tài)內(nèi)容并跳過。這可以用于優(yōu)化更新性能。
<span v-once>This will never change: {{msg}}</span>

2、組件化與應(yīng)用構(gòu)建

import的名字!==下面components的名字==調(diào)用時候的標(biāo)簽名字,然后把import的源文件里的template里的div渲染給網(wǎng)頁。

文件名:MyComponent
路徑:../../components/MyComponent
導(dǎo)入:import MyComponent from '../../components/MyComponent'
聲明:components:{
        my-components : MyComponent
    }
使用:<my-components></my-components>

在一個大型應(yīng)用中,有必要將整個應(yīng)用程序劃分為組件,以使開發(fā)更易管理。在后續(xù)教程中我們將詳述組件,不過這里有一個 (假想的) 例子,以展示使用了組件的應(yīng)用模板是什么樣的:

<div id="app">
    <app-nav></app-nav>
    <app-view>
    <app-sidebar></app-sidebar>
    <app-content></app-content>
    </app-view>
</div>

3、數(shù)組更新機(jī)制

為了解決第一類問題,以下兩種方式都可以實現(xiàn)和 vm.items[indexOfItem] = newValue 相同的效果,同時也將觸發(fā)狀態(tài)更新:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

為了解決第二類問題,你可以使用 splice:
vm.items.splice(newLength)

4、對象更改檢測

Vue.set(vm.userProfile, 'age', 27)

5、組件怎么顯示

5.1、全局注冊

在腳手架創(chuàng)建的項目中,通過在main.js中聲明

Vue.component('button-counter', {
        data: function () {
                        return {
                          count: 0
                        }
        },
        template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

然后在頁面app.vue中引用button-counter即可
這樣看起來更加清晰:

Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })
new Vue({ el: '#app' })
<div id="app">
  <component-a></component-a>
  <component-b></component-b>
  <component-c></component-c>
</div>
5.2、局部注冊
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然后在 components 選項中定義你想要使用的組件:

new Vue({
  el: '#app'
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})
5.3、Babel和webpack的模塊系統(tǒng)

然后你需要在局部注冊之前導(dǎo)入每個你想使用的組件。例如,在一個假設(shè)的ComponentB.js或ComponentB.vue文件中。
我們推薦創(chuàng)建一個 components 目錄,并將每個組件放置在其各自的文件中。

import ComponentA from './ComponentA'
import ComponentC from './ComponentC'

export default {
  components: {
    ComponentA,
    ComponentC
  },
  // ...
}

}
import Vue from 'vue';
import MyComponent from '@/components/MyComponent.vue'; // 導(dǎo)入自己寫的組件文件
 
Vue.use(MyComponent); // 自定義全局組件的時候需要Vue.use();
 
Vue.component('my-component', MyComponent); //初始化組件
 
new Vue({
  el: '#app',
  router,
  components: {
    App,
    MyComponent
  },
  template: '<App/>',
});
1、先寫組件
var tempalateDiv;
2、把組件寫進(jìn)一個對象里
var templateObject = {
    props: ['product'],
    template: tempalateDiv,
      methods: {
            increaseSales: function () {
                this.product.sale = parseInt(this.product.sale);
              this.product.sale += 1
              this.$emit('increment')
            }
      }
}
3、生命全局組件
Vue.component('product', templateObject)

二、Vue.js 組件編碼規(guī)范

本規(guī)范提供了一種統(tǒng)一的編碼規(guī)范來編寫 Vue.js 代碼。這使得代碼具有如下的特性:

  • 其它開發(fā)者或是團(tuán)隊成員更容易閱讀和理解。
  • IDEs 更容易理解代碼,從而提供高亮、格式化等輔助功能
  • 更容易使用現(xiàn)有的工具
  • 更容易實現(xiàn)緩存以及代碼包的分拆

參考鏈接

1、組件名稱用橫線-連接

<!-- 推薦 -->
<app-header></app-header>
<user-list></user-list>
<range-slider></range-slider>

<!-- 避免 -->
<btn-group></btn-group> <!-- 雖然簡短但是可讀性差. 使用 `button-group` 替代 -->
<ui-slider></ui-slider> <!-- ui 前綴太過于寬泛,在這里意義不明確 -->
<slider></slider> <!-- 與自定義元素規(guī)范不兼容 -->

2、組件結(jié)構(gòu)化

<template lang="html">
  <div class="Ranger__Wrapper">
    <!-- ... -->
  </div>
</template>

<script type="text/javascript">
  export default {
    // 不要忘記了 name 屬性
    name: 'RangeSlider',
    // 使用組件 mixins 共享通用功能
    mixins: [],
    // 組成新的組件
    extends: {},
    // 組件屬性、變量
    props: {
      bar: {}, // 按字母順序
      foo: {},
      fooBar: {},
    },
    // 變量
    data() {},
    computed: {},
    // 使用其它組件
    components: {},
    // 方法
    watch: {},
    methods: {},
    // 生命周期函數(shù)
    beforeCreate() {},
    mounted() {},
  };
</script>

<style scoped>
  .Ranger__Wrapper { /* ... */ }
</style>

3、子組件父組件

<div id="app">
    //父組件
    <my-component message="來自父組件的數(shù)據(jù)"></my-component>
</div>
<script>
    //子組件
    Vue.component('my-component',{
        props:['message'],
        template:`<div>{{message}}</div>`
    })
    var app=new Vue({
        el:'#app'
    })
</script>

4、謹(jǐn)慎使用 this.$refs

<!-- 推薦,并未使用 this.$refs -->
<range :max="max"
  :min="min"
  @current-value="currentValue"
  :step="1"></range>
<!-- 使用 this.$refs 的適用情況-->
<modal ref="basicModal">
  <h4>Basic Modal</h4>
  <button class="primary" @click="$refs.basicModal.hide()">Close</button>
</modal>
<button @click="$refs.basicModal.open()">Open modal</button>

<!-- Modal component -->
<template>
  <div v-show="active">
    <!-- ... -->
  </div>
</template>

<script>
  export default {
    // ...
    data() {
      return {
        active: false,
      };
    },
    methods: {
      open() {
        this.active = true;
      },
      hide() {
        this.active = false;
      },
    },
    // ...
  };
</script>
<!-- 如果可通過 emited 來做則避免通過 this.$refs 直接訪問 -->
<template>
  <range :max="max"
    :min="min"
    ref="range"
    :step="1"></range>
</template>

<script>
  export default {
    // ...
    methods: {
      getRangeCurrentValue() {
        return this.$refs.range.currentValue;
      },
    },
    // ...
  };
</script>

5、使用組件名作為樣式作用域空間

使用組件名作為樣式命名的前綴,可基于 BEM 或 OOCSS 范式。
同時給 style 標(biāo)簽加上 scoped 屬性。
加上 scoped 屬性編譯后會給組件的 class 自動加上唯一的前綴從而避免樣式的沖突。

<style scoped>
  /* 推薦 */
  .MyExample { }
  .MyExample li { }
  .MyExample__item { }

  /* 避免 */
  .My-Example { } /* 沒有用組件名或模塊名限制作用域, 不符合 BEM 規(guī)范 */
</style>

6、提供組件 API 文檔

在模塊目錄中添加 README.md 文件:

range-slider/
├── range-slider.vue
├── range-slider.less
└── README.md

在 README 文件中說明模塊的功能以及使用場景。對于 vue 組件來說,比較有用的描述是組件的自定義屬性即 API 的描述介紹。

README.md

功能

range slider 組件可通過拖動的方式來設(shè)置一個給定范圍內(nèi)的數(shù)值。

該模塊使用 noUiSlider 來實現(xiàn)跨瀏覽器和 touch 功能的支持。

如何使用

<range-slider> 支持如下的自定義屬性:

attribute type description
min Number 可拖動的最小值.
max Number 可拖動的最大值.
values Number[] optional 包含最大值和最小值的數(shù)組. 如. values="[10, 20]". Defaults to [opts.min, opts.max].
step Number optional 增加減小的數(shù)值單位,默認(rèn)為 1.
on-slide Function optional 用戶拖動開始按鈕或者結(jié)束按鈕時的回調(diào)函數(shù),函數(shù)接受 (values, HANDLE) 格式的參數(shù)。 如: on-slide={ updateInputs }, component.updateInputs = (values, HANDLE) => { const value = values[HANDLE]; }.
on-end Function optional 當(dāng)用戶停止拖動時觸發(fā)的回調(diào)函數(shù),函數(shù)接受 (values, HANDLE) 格式的參數(shù)。

如需要自定義 slider 的樣式可參考 noUiSlider 文檔

7、盡可能使用 mixins

為什么?

Mixins 封裝可重用的代碼,避免了重復(fù)。如果兩個組件共享有相同的功能,則可以使用 mixin。通過 mixin,你可以專注于單個組件的任務(wù)和抽象的通用代碼。這有助于更好地維護(hù)你的應(yīng)用程序。

怎么做?

假設(shè)你有一個移動端和桌面端的菜單組件,它們共享一些功能。我們可以抽象出這兩個組件的核心功能到一個 mixin 中,例如:

const MenuMixin = {
  data () {
    return {
      language: 'EN'
    }
  },

  methods: {
    changeLanguage () {
      if (this.language === 'DE') this.$set(this, 'language', 'EN')
      if (this.language === 'EN') this.$set(this, 'language', 'DE')
    }
  }
}

export default MenuMixin

要使用 mixin,只需將其導(dǎo)入到兩個組件中(我只展示移動組件)。

<template>
  <ul class="mobile">
    <li @click="changeLanguage">Change language</li>
  </ul>
</template>

<script>
  import MenuMixin from './MenuMixin'

  export default {
    mixins: [MenuMixin]
  }
</script>

8、組件選項的順序

組件選項應(yīng)該有統(tǒng)一的順序。

export default {
  name: '',

  mixins: [],

  components: {},

  props: {},

  data() {},

  computed: {},

  watch: {},

  created() {},

  mounted() {},

  destroyed() {},

  methods: {}
};

9、ESLINT

module.exports = {
  root: true,
  parserOptions: {
    parser: 'babel-eslint',
    sourceType: 'module'
  },
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  extends: ['plugin:vue/recommended', 'eslint:recommended'],

  // add your custom rules here
  //it is base on https://github.com/vuejs/eslint-config-vue
  rules: {
    "vue/max-attributes-per-line": [2, {
      "singleline": 10,
      "multiline": {
        "max": 1,
        "allowFirstLine": false
      }
    }],
    "vue/name-property-casing": ["error", "PascalCase"],
    'accessor-pairs': 2,
    'arrow-spacing': [2, {
      'before': true,
      'after': true
    }],
    'block-spacing': [2, 'always'],
    'brace-style': [2, '1tbs', {
      'allowSingleLine': true
    }],
    'camelcase': [0, {
      'properties': 'always'
    }],
    'comma-dangle': [2, 'never'],
    'comma-spacing': [2, {
      'before': false,
      'after': true
    }],
    'comma-style': [2, 'last'],
    'constructor-super': 2,
    'curly': [2, 'multi-line'],
    'dot-location': [2, 'property'],
    'eol-last': 2,
    'eqeqeq': [2, 'allow-null'],
    'generator-star-spacing': [2, {
      'before': true,
      'after': true
    }],
    'handle-callback-err': [2, '^(err|error)$'],
    'indent': [2, 2, {
      'SwitchCase': 1
    }],
    'jsx-quotes': [2, 'prefer-single'],
    'key-spacing': [2, {
      'beforeColon': false,
      'afterColon': true
    }],
    'keyword-spacing': [2, {
      'before': true,
      'after': true
    }],
    'new-cap': [2, {
      'newIsCap': true,
      'capIsNew': false
    }],
    'new-parens': 2,
    'no-array-constructor': 2,
    'no-caller': 2,
    'no-console': 'off',
    'no-class-assign': 2,
    'no-cond-assign': 2,
    'no-const-assign': 2,
    'no-control-regex': 0,
    'no-delete-var': 2,
    'no-dupe-args': 2,
    'no-dupe-class-members': 2,
    'no-dupe-keys': 2,
    'no-duplicate-case': 2,
    'no-empty-character-class': 2,
    'no-empty-pattern': 2,
    'no-eval': 2,
    'no-ex-assign': 2,
    'no-extend-native': 2,
    'no-extra-bind': 2,
    'no-extra-boolean-cast': 2,
    'no-extra-parens': [2, 'functions'],
    'no-fallthrough': 2,
    'no-floating-decimal': 2,
    'no-func-assign': 2,
    'no-implied-eval': 2,
    'no-inner-declarations': [2, 'functions'],
    'no-invalid-regexp': 2,
    'no-irregular-whitespace': 2,
    'no-iterator': 2,
    'no-label-var': 2,
    'no-labels': [2, {
      'allowLoop': false,
      'allowSwitch': false
    }],
    'no-lone-blocks': 2,
    'no-mixed-spaces-and-tabs': 2,
    'no-multi-spaces': 2,
    'no-multi-str': 2,
    'no-multiple-empty-lines': [2, {
      'max': 1
    }],
    'no-native-reassign': 2,
    'no-negated-in-lhs': 2,
    'no-new-object': 2,
    'no-new-require': 2,
    'no-new-symbol': 2,
    'no-new-wrappers': 2,
    'no-obj-calls': 2,
    'no-octal': 2,
    'no-octal-escape': 2,
    'no-path-concat': 2,
    'no-proto': 2,
    'no-redeclare': 2,
    'no-regex-spaces': 2,
    'no-return-assign': [2, 'except-parens'],
    'no-self-assign': 2,
    'no-self-compare': 2,
    'no-sequences': 2,
    'no-shadow-restricted-names': 2,
    'no-spaced-func': 2,
    'no-sparse-arrays': 2,
    'no-this-before-super': 2,
    'no-throw-literal': 2,
    'no-trailing-spaces': 2,
    'no-undef': 2,
    'no-undef-init': 2,
    'no-unexpected-multiline': 2,
    'no-unmodified-loop-condition': 2,
    'no-unneeded-ternary': [2, {
      'defaultAssignment': false
    }],
    'no-unreachable': 2,
    'no-unsafe-finally': 2,
    'no-unused-vars': [2, {
      'vars': 'all',
      'args': 'none'
    }],
    'no-useless-call': 2,
    'no-useless-computed-key': 2,
    'no-useless-constructor': 2,
    'no-useless-escape': 0,
    'no-whitespace-before-property': 2,
    'no-with': 2,
    'one-var': [2, {
      'initialized': 'never'
    }],
    'operator-linebreak': [2, 'after', {
      'overrides': {
        '?': 'before',
        ':': 'before'
      }
    }],
    'padded-blocks': [2, 'never'],
    'quotes': [2, 'single', {
      'avoidEscape': true,
      'allowTemplateLiterals': true
    }],
    'semi': [2, 'never'],
    'semi-spacing': [2, {
      'before': false,
      'after': true
    }],
    'space-before-blocks': [2, 'always'],
    'space-before-function-paren': [2, 'never'],
    'space-in-parens': [2, 'never'],
    'space-infix-ops': 2,
    'space-unary-ops': [2, {
      'words': true,
      'nonwords': false
    }],
    'spaced-comment': [2, 'always', {
      'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
    }],
    'template-curly-spacing': [2, 'never'],
    'use-isnan': 2,
    'valid-typeof': 2,
    'wrap-iife': [2, 'any'],
    'yield-star-spacing': [2, 'both'],
    'yoda': [2, 'never'],
    'prefer-const': 2,
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
    'object-curly-spacing': [2, 'always', {
      objectsInObjects: false
    }],
    'array-bracket-spacing': [2, 'never']
  }
}

三、前端路由與Vue-router

1、基本用法

  • 在main.js里使用Vue.use()加載插件
  • 創(chuàng)建一個數(shù)組來自定路由匹配列表
  • 繼續(xù)在main.js中完成配置和路由實例
  • 在根實例app.vue中添加一個路由視圖<router-view>來掛載所有的路由組件

1、在main.js里使用Vue.use()加載插件

import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './app.vue'

Vue.use(VueRouter);

2、創(chuàng)建一個數(shù)組來自定路由匹配列表,每一個路由映射一個組件:

const Routers = [
    {
        path:'/index',
        components:(resolve) => require(['./views/index.vue'],resolve)
    },
    {
        path:'/about',
        components:(resolve) => require(['./views/about.vue'],resolve)
    },
    {
        path:'/user:id',
        component:(resolve) => require(['./views/user.vue],resolve)
    }
    {
        path:'*',
        redirect:'/index'
    }
]
//在路由列表里,可以再最后添加意向,當(dāng)訪問的路徑不存在時,重定向到首頁。
//通過this.$route.params.id獲取到id,然后進(jìn)行分發(fā)

3、繼續(xù)在main.js中完成配置和路由實例

const RouterConfig={
    //使用HTML5的History路由模式
    mode: 'history',
    routers: Routers
};
const router = new VueRouter(RouterConfig);

new Vue({
    el:'#app',
    router:router,
    render: h => {
        return h(App)
    }
})

4、在根實例app.vue中添加一個路由視圖

<template>
    <div>
        <router-view></router-view>
    </div>
</template>
<script>
export default{
    
}
</script>
//運行網(wǎng)頁時,<router-view>會根據(jù)當(dāng)前路由動態(tài)渲染不同的頁面組件。網(wǎng)頁中一些公共部分,比如頂部的導(dǎo)航欄,側(cè)邊導(dǎo)航欄,底部的版權(quán)信息,這些也可以直接寫在app.vue中,與<router-view>同級。路由切換時,切換的時<router-view>掛載的組件,其他的內(nèi)容不會變化。

2、跳轉(zhuǎn)

方式1:
直接修改地址欄

方式2:
this.$router.push(‘路由地址’);
this.$router.replace(‘路由地址’);
this.$router.go(int);

router.push({ path: 'home' })
// 命名的路由
router.push({
  name: 'user', 
  params: { 
    userId: 123 
  }
})
// 帶查詢參數(shù),變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
方式3:
<router-link to="路由地址" replace></router-link>
使用replace不會留下History記錄,不能用后退鍵返回上一個頁面

3、vue-router的高級用法

場景:如何修改spa項目的網(wǎng)頁標(biāo)題

比較理想的一個思路是,在頁面發(fā)生路由改變時,統(tǒng)一設(shè)置。vue-router提供了導(dǎo)航鉤子beforeEach和afterEach,他們會在路由即將改變前和改變后觸發(fā),所以設(shè)置標(biāo)題可以在beforeEach鉤子完成。

const Routers= [
    {
        path:'/index',
        meta:{
            title: '首頁'
        },
        component:(resolve) => require(['./views/index.vue'],resolve)
    }
];

const router = new VueRouter(RouterConfig);
router.brforeEach((to,from,next) =>{
                    window.document.title = to.meta.title;
                    next();
                } 
);

導(dǎo)航鉤子有三個參數(shù):

to:即將進(jìn)入的目標(biāo)的路由對象

from:當(dāng)前導(dǎo)航即將要離開的路由對象

next:調(diào)用該方法后,才能進(jìn)入下一個鉤子

場景:返回上一個頁面,滾動條的位置

router.afterEach((to,from,next) => {
    window.scrollTo(0,0);
})

場景三:檢驗登錄

router.beforeEach((to,from,next) => {
    if('登陸了'){
        next();
    }else{
        next('/login');
    }
})

4、路由器懶加載

結(jié)合這兩者,這就是如何定義一個能夠被 Webpack 自動代碼分割的異步組件。

const Foo = () => import('./Foo.vue')

在路由配置中什么都不需要改變,只需要像往常一樣使用 Foo

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

四、狀態(tài)管理與Vuex

場景:跨組件共享數(shù)據(jù)的需求

1、基本用法

基本用法同vue-router

數(shù)據(jù)保存在Vuex選項的state字段內(nèi)

const store = new Vuex.Store({
    state:{
        count:0
    }
})

在任何組件內(nèi),可以直接通過$store.state.count讀取

Vuex 中的 mutation 也需要與使用 Vue 一樣遵守一些注意事項:
1.最好提前在你的 store 中初始化好所有所需屬性。
2.當(dāng)需要在對象上添加新屬性時,你應(yīng)該使用 Vue.set(obj, 'newProp', 123), 或者
以新對象替換老對象:state.obj = { ...state.obj, newProp: 123 }
一般會獨立開來(使用mutation-types.js存放mutation常量)如:

//mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'

// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 我們可以使用 ES2015 風(fēng)格的計算屬性命名功能來使用一個常量作為函數(shù)名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

問題

1、修改mintui樣式

修改樣式的核心是:自己寫的樣式優(yōu)先級>第三方組件樣式。

以此為原則:1)使用!important提升優(yōu)先級 2)main.js映入第三方組件后面,引入自定義的樣式表,webpack打包后樣式會覆蓋。

找到頁面中的css進(jìn)行覆蓋。

內(nèi)容居左:
text-align:left
<div style="text-align:center">
  <span>span的居中可以通過放置在div中,然后讓div text-align實現(xiàn)居中</span>
</div>

2、路由跳轉(zhuǎn)

https://blog.csdn.net/qq_15646957/article/details/78070862

1.Params

由于動態(tài)路由也是傳遞params的,所以在 this.$router.push() 方法中path不能和params一起使用,否則params將無效。需要用name來指定頁面。

2.Query

頁面通過path和query傳遞參數(shù),該實例中row為某行表格數(shù)據(jù)

在目標(biāo)頁面通過this.$route.query獲取參數(shù):

this.$route.query.row.xxx

3、異步問題

因為要等到頁面更新過之后才能執(zhí)行某些操作,所以用:

vm.$nextTick( [callback] )

示例

new Vue({
  // ...
  methods: {
    // ...
    example: function () {
      // 修改數(shù)據(jù)
      this.message = 'changed'
      // DOM 還沒有更新
      this.$nextTick(function () {
        // DOM 現(xiàn)在更新了
        // `this` 綁定到當(dāng)前實例
        this.doSomethingElse()
      })
    }
  }
})

4、axios請求中

當(dāng)請求成功時,會執(zhí)行 .then,否則執(zhí)行 .catch

這兩個回調(diào)函數(shù)都有各自獨立的作用域,如果直接在里面訪問 this,無法訪問到 Vue 實例

這時只要添加一個 .bind(this) 就能解決這個問題

.then(function(res){
  console.log(this.data)
}.bind(this))

5、局部修改第三方組件庫樣式

為什么需要穿透scoped?

scoped看起來很美,但是,在很多項目中,會出現(xiàn)這么一種情況,即:引用了第三方組件,需要在組件中局部修改第三方組件的樣式,而又不想去除scoped屬性造成組件之間的樣式污染。此時只能通過特殊的方式,穿透scoped。

<style scoped>
    外層 >>> 第三方組件 {
        樣式
    }
#myCell >>> .van-cell__value {
  color: #ff0000;
}
</style>    

具體參考:https://www.cnblogs.com/karthuslorin/p/9038854.html

修改element樣式問題: 用ui組件總免不了需要對它做一些個性化定制的需求,所以我們就要覆蓋element的一些樣式。 首先我們要了解一下vue scoped是什么,很多人非常喜歡用scoped,媽媽再也不用擔(dān)心樣式?jīng)_突問題了,其實scoped也沒有很神秘的,它就是基于PostCss的,加了一個作用局的概念。

//編譯前
.example {
  color: red;
}
//編譯后
.example[_v-f3f3eg9] {
  color: red;
}
復(fù)制代碼

它和我們傳統(tǒng)的命名空間的方法避免css沖突沒有什么本質(zhì)性的區(qū)別。 現(xiàn)在我們來說說怎么覆蓋element-ui樣式。由于element-ui的樣式我們是在全局引入的,所以你想在某個view里面覆蓋它的樣式就不能加scoped,但你又想只覆蓋這個頁面的element樣式,你就可在它的父級加一個class,以用命名空間來解決問題。

.aritle-page{ //你的命名空間
    .el-tag { //element-ui 元素
      margin-right: 0px;
    }
}

建議向樓主一樣專門建一個scss文件里專門自定義element-ui的各種樣式

6、vscode的eslint

{
  "workbench.colorTheme": "One Dark Pro",
  "editor.formatOnSave": true,
  "editor.formatOnType": false,
  "editor.minimap.enabled": false,
  "vetur.format.defaultFormatter.html": "js-beautify-html",
  "vsicons.dontShowNewVersionMessage": true,
  "eslint.autoFixOnSave": true,
  "eslint.validate": [
    "javascript",
    {
      "language": "vue",
      "autoFix": true
    },
    "html",
    "vue"
  ],
  "prettier.eslintIntegration": true,
  "workbench.iconTheme": "material-icon-theme",
  "terminal.integrated.shell.windows": "C:\\\\Windows\\\\System32\\\\cmd.exe",
  "eslint.run": "onSave"
}

7、屏幕適配

分辨率:1334pt x 750pt
指的是屏幕上垂直有1136個物理像素,水平有750個物理像素。

屏幕尺寸:4.7in
注意英寸是長度單位,不是面積單位。4.7英寸指的是屏幕對角線的長度,1英寸等于2.54cm。

屏幕像素密度:326ppi
指的是每英寸屏幕所擁有的像素數(shù),在顯示器中,dpi=ppi。dpi強(qiáng)調(diào)的是每英寸多少點。
同時,屏幕像素密度=分辨率/屏幕尺寸

然而,這段代碼其實也并不完美,在IE瀏覽器中,由于橫屏豎屏的切換會對其造成影響。
為了解決這個兼容性的問題,最后再加上一句,就有了現(xiàn)在的:
響應(yīng)式布局:
<meta name = "viewport" content = "width=device-width,initial-scale=1" >
media="(orientation:landscape) and (min-width:500px)"橫向 
media="(max-width:500px)"


<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
在這個里面主要有這幾個屬性:
width             - viewport的寬度 
height            - viewport的高度
initial-scale     - 初始的縮放比例
minimum-scale     - 允許用戶縮放到的最小比例
maximum-scale     - 允許用戶縮放到的最大比例
user-scalable     - 用戶是否可以手動縮放

如果要禁止頁面縮放,只要把user-scalable 設(shè)置成no 就可以

8、滾動條

有時候我們需要頁面滾動條滾動到某一固定的位置,一般使用Window scrollTo()方法。

語法就是:scrollTo(xpos,ypos)

xpos:必需。要在窗口文檔顯示區(qū)左上角顯示的文檔的 x 坐標(biāo)。

ypos:必需。要在窗口文檔顯示區(qū)左上角顯示的文檔的 y 坐標(biāo)。

例如滾動內(nèi)容的坐標(biāo)位置100,500:

window.scrollTo(100,500);

Your Repositorie項目

一、頁面布局

1、邊距問題

  • 首先在html里面設(shè)置全局

    body {
        margin: 0px;
        padding: 0px;
    }
    
  • 其次在App.vue里面設(shè)置

  <div id="app">
    <x-header :left-options="{showBack: false}">
      <x-icon type="github" class="icon-style" />
      {{ title }}
      <a v-show="token" slot="right" @click="handleLogout">logout</a>
    </x-header>
    <box gap="10px 10px">
      <router-view />
    </box>
  </div>
<style lang="less">
.icon-style {
  width: 30px;
  vertical-align: middle;
  margin-right: 6px;
}
</style>

使用box設(shè)置<router-view />的頁面邊距

二、svg在vux中的使用

1、在vue項目中使用

在沒有其他組件庫的情況下,需要安裝第三方插件vue-svg-icon
步驟如下:

  • 安裝第三方插件
    npm i vue-svg-icon
  • 在入口文件main.js引入
import Vue from from 'vue'
import Icon from 'vue-svg-icon/Icon.vue' //引入
Vue.component('icon', Icon) //注冊
  • 將下載好的svg資源放到src\assets\svg中
  • 使用:
<icon name="example"></icon>

name的值為svg文件名

2、在vux組件庫中的使用

官方文檔鏈接:
https://doc.vux.li/zh-CN/components/x-icon.html
官方文檔說的不夠詳細(xì),具體使用如下:

  • 將下載好的svg資源放在node_modules\vux\src\icons下
  • 在組件中直接使用
<x-icon type="ios-arrow-up" class="icon-red"></x-icon>

type的值為svg文件名,class為你要自定義的樣式

三、alias

文件的引用

alias(在webpack配置文件里面改)

VUE-CLI 3

1、打開cmd,輸入vue ui

VUE實現(xiàn)局部刷新

利用Vue里面的provide+inject組合

  • 首先需要修改App.vue

    //App.vue
    <template>
      <div id="app">
        <div>
          <router-view v-if="isRouterAlive" />
        </div>
      </div>
    </template>
    <script>
    export default {
      name: 'App',
      provide() {
        return {
          reload: this.reload
        }
      },
      data() {
        return {
          isRouterAlive: true
        }
      },
      methods: {
        reload() {
          this.isRouterAlive = false
          this.$nextTick(() => {
            this.isRouterAlive = true
          })
        }
      }
    }
    </script>
    
  • 其次到需要刷新的頁面進(jìn)行引用

    使用inject導(dǎo)入引用reload

     inject: ['reload'],
     this.reload()
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ## 框架和庫的區(qū)別?> 框架(framework):一套完整的軟件設(shè)計架構(gòu)和**解決方案**。> > 庫(lib...
    Rui_bdad閱讀 3,150評論 1 4
  • vue筆記 一.vue實例 vue的生命周期 beforeCreate(創(chuàng)建前), created(創(chuàng)建后), b...
    秋殤1002閱讀 1,125評論 0 1
  • vue中的MVVM模式 即Model-View-ViewModel。 Vue是以數(shù)據(jù)為驅(qū)動的,Vue自身將DOM和...
    w_zhuan閱讀 318評論 0 1
  • VUE介紹 Vue的特點構(gòu)建用戶界面,只關(guān)注View層簡單易學(xué),簡潔、輕量、快速漸進(jìn)式框架 框架VS庫庫,是一封裝...
    多多醬_DuoDuo_閱讀 2,853評論 1 17
  • ..
    李華炎閱讀 254評論 0 1

友情鏈接更多精彩內(nèi)容