DWBBlog


  • Home

  • Archives

十、react进阶(事件处理和条件渲染)

Posted on 2019-11-22

1. 条件渲染

(1)if - else 条件渲染

1
2
3
4
5
6
7
8
9
export default function Greeting (props){
var flag = props.flag;
if(flag){
return <div>登录成功</div>
}
else{
return <div>登录失败</div>
}
}

(2)&& 逻辑与条件渲染

1
2
3
4
5
export default function Greeting (props){
return props.flag.length >0 && (props.flag.map(item =>{
return <p key={item}>{item}</p>
}))
}
  • 需要注意的是数组的函数传值是 通过 进行的,而不是把数组展开,那样子就会变成一个对象

(3)三元表达式渲染

1
2
3
export default function Greeting (props){
return props.flag==true?<div>登录成功</div>:<div>登陆失败</div>
}

(4)阻止组件渲染

1
2
3
4
5
6
7
8
export default function Greeting (props){
var flag = props.flag;
if(flag == false){

return null; ★★
}
return <div>登录成功</div>
}

2. 列表渲染

1
2
3
4
5
6
7
8
import React from 'react'
export default function List(props) {
const numbers = props.numbers;
const listItem = numbers.map(item => {
return <li key={item}>{item}</li>
})
return listItem.length > 0 ? <ul>{listItem}</ul> : null
}

2.1 Fragment 的使用 ★

n. 碎片; 片段;
v. (使) 碎裂,破裂,分裂
1
2
3
4
5
6
7
8
9
10
export default function List(props) {
const numbers = props.numbers;
const liItems = numbers.map(item => {
return <React.Fragment key={item.title}>
<dt>{item.title}</dt>
<dd>{item.msg}</dd>
</React.Fragment>
})
return liItems.length>0?(<dl>{liItems}</dl>):null;
}

jsx 表达式必须在一个根节点里面,使用 <React.Fragment>将其包裹在里面 。

2.2 react组合(类似vue中slot)

1
2
3
4
5
6
7
8
9
10
11
export default function FancyBorder(props) {
return <div className="child">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
{props.children}
</div>
}
1
2
3
4
ReactDom.render(<FancyBorder left={<div>左边内容</div>} right={<div>右边内容</div>}>
<span>这是span</span>
<p>这是p</p>
</FancyBorder>,document.getElementById("app"))

3. style 的使用

3.1 style.js

1
2
3
4
5
6
7
8
9
render(){
return
<h1 style= {{color:'red',fontSize:"18px",marginTop:"100px"}}>
这是评论列表组件
</h1>
}
// user: { fontSize: '14px' },
// 为什么两个{{}} ,可以理解成第一个{}为赋值已给一个 user 对象的括号 ,
// 再把这个 user 对象赋值给 style 即可 ,所以有两个 {{ }}
1
2
3
4
5
6
//写成 style.js 样式 , 变成独立的文件
export default {
item: { border: '1px dashed #ccc', margin: '10px', padding: '10px', boxShadow: '0 0 10px #ccc' },
user: { fontSize: '14px', paddingLeft:"10px"},
content: { fontSize: '12px',float:"right" }
}

3.2 css 样式表 ★

1.安装 css 加载器 ★

修改 webpack.config.js这个配置文件,为 css-loader 添加参数:

1
2
3
npm install  style-loader  css-loader -D

{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
  1. 导入样式表
1
2
3
4
5
6
7
8
9
10
11
import   "./cmtlist.css"

.title{
color: red;
text-align: center;
font-weight: 200;
}

h1{
font-style: italic;
}

css 模块化只针对类选择器 和 Id选择器生效, 不会对标签选择器模块化

3.开启模块作用域 ★

1
2
#1. webpack.config.js  修改css的rules规则,开启css的模块化
{ test: /\.css$/, use: ['style-loader', 'css-loader?modules'] } //modules表示为css启动模块化(启动模块化之后就有模块作用域)

4.css 模块化的注意点

1
2
3
4
/*默认情况下,所有的类和id样式都会被模块化*/
/*使用:local()包裹的样式会被模块化,但是对于标签名的样式无效 :local默认可以省略*/
/*使用:global包裹的样式不会被模块化*/
/*但是标签名的样式不会被模块化*/

一般在开发过程中,我们需要引入很多的第三方css文件,为了让第三方css文件能够被友好的使用,我们一般不会对css文件开启模块化,一般都会给自己写的less 、 sass文件开启模块化。★★★

5.用 :global()包裹的样式不会被模块化 , 使用:local() 包裹的样式会被模块化,但是对于标签名的样式无效,还有默认就是local,可以省略。

4. react的事件处理

  • 如果handleClick2是箭头函数,则函数中的this默认指向当前组件对象
  • 如果handleClick2是普通函数,则函数中的this默认指向undefine
1
<button onClick={this.handleClick2}>点我3</button>

4.1 this 的问题

修改事件函数中this指向问题:
1.直接声明函数为箭头函数,此时函数中的this指向当前组件对象
2.绑定事件的时候,通过bind方法来修改this指向

1
onClick={this.handleClick2.bind(this,'xx')}

​ 3.在构造函数中通过bind修改this指向

1
2
3
4
5
 constructor() {
super();
//在构造函数中改变this.handleClick2函数的this指向
this.handleClick2 = this.handleClick2.bind(this)
}

4.2 传参的问题★★

1.使用箭头函数传递参数

1
2
onClick={() => this.handleClick("click")
onClick={(e)=>this.handleClick2(e,"参数信息")}

差别在于第二个写法会传递一个事件对象过去,然后我们可以通过该事件对象阻止

默认事件等等 , e.preventDefault 阻止默认事件 。★

2.通过bind来传递参数

1
onClick={this.handleClick2.bind(this,'xx')}

缺陷是不能传递事件对象

5. 受控组件和非受控组件

5.1 受控组件

受控组件又称为智能组件,顾名思义受控组件就是受到控制的组件,受控组件是数据的所有者,它拥有数据、且拥有操作数据的action。它可以使用自己的state数据,也可以将数据和操作action传递给子组件,让子组件来完成UI或者功能。

1
2
3
4
5
6
<input type="text" value={this.state.age} onChange = {this.handleChange}/> 改不动的 value

handleChange = (e)=>{
this.setState({age:e.target.value})
console.log(this.state.age,"受控组件")
}

5.2 非受控组件

非受控组件不同于受控组件,它自身并不能拥有可改变的数据。因为函数组件只负责接收 props 并返回 UI,在真实的 React 应用开发场景下,我们经常尽可能的使用函数组件,将整个应用的 UI 拆分成尽可能小的视觉单元。

1
2
3
4
5
6
<input type="text" ref="txt" defaultValue={this.state.age} onChange = {this.handleChange2}/>

handleChange2 = (e)=>{
console.log(e.target.value,"这是非受控组件")
console.log(this.refs.txt.value,"这是ref绑定的值")
}

6. ref的用法

6.1 普通的用法

  • ref 绑定一个普通的字符串
1
2
3
4
5
6
7
{ ref绑定一个普通字符串*/}
<input type="text" ref="txt" defaultValue={this.props.default} onChange={this.handleChange2} />

handleChange2 = (e)=>{
console.log(e.target.value,"这是非受控组件")
console.log(this.refs.txt.value,"这是ref绑定的值")
}

6.2 React.createRef方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
constructor(){
super()
this.state = {
age:"21"
}
this.textInput = React.createRef(); ★
//在构造器中
}


handleChange3 =()=>{
console.log(this.textInput.current.value) ★★
//使用的方法 this.textInput.current.value
}

6.3 ref绑定回调函数

1
2
3
4
5
6
7
8
9
10
11
//ref绑定回调函数
<input type="text"
ref={input=>{this.input = input}} ★★★
// ref={input=>{this.input = input}} 使用箭头函数进行构造
defaultValue={this.props.default}
onChange={this.handleChange4} />

handleChange4 = ()=>{
console.log(this.input.value) ★
// 输出使用的方法
}

6.4 ref 的转发

Ref 转发是一个可选特性,其允许某些组件接收 ref,并将其向下传递(换句话说,“转发”它)给子组件。

简单解释:就是通过传递参数赋值的思想把父组件的 ref 赋值给子组件的 ref

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));

// 你可以直接获取 DOM button 的 ref:
const ref = React.createRef();
<FancyButton ref={ref}>点击我!</FancyButton>;

/*
以下是对上述示例发生情况的逐步解释:
1.我们通过调用 React.createRef 创建了一个 React ref 并将其赋值给 ref 变量。
2.我们通过指定 ref 为 JSX 属性,将其向下传递给 <FancyButton ref={ref}>。
3.React 传递 ref 给 fowardRef 内函数 (props, ref) => ...,作为其第二个参数。
4.我们向下转发该 ref 参数到 <button ref={ref}>,将其指定为 JSX 属性。
5.当 ref 挂载完成,ref.current 将指向 <button> DOM 节点。
*/

九.react起始简介

Posted on 2019-11-21

1. MVC的简介

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。

2.Vuex 和 Redux 的区别

Redux 使用的是不可变数据,而Vuex的数据是可变的。Redux每次都是用新的state替换旧的state,而Vuex是直接修改

Redux 在检测数据变化的时候,是通过的方式比较差异的,而其实和的原理一样,是通过来比较的(如果看源码会知道,其实他内部直接创建一个实例用来跟踪数据变化)

3. vue 和 react 监听数据的原理

  • vue中借助Object.defineProperty(getter setter) 做数据劫持

  • react很大程度上是通过比较对象的引用地址是否一致来看数据有没有变化(react中大量使用了不可变对象)

4. react 安装的目录

4.1 全局安装 webpack

1
2
3
4
5
6
2.1	构建webpack应用
运行npm init -y 快速初始化项目
npm install webpack@4.27.1 -d
npm install webpack-cli -d 提供一些基本命令(比如webpack命令)
npm install webpack-dev-server –d
npm i html-webpack-plugin@3.2.0 --save-dev

4.2 创建webpack 应用

1.src文件夹 目录下的 index.html 、main.js

  1. dist 文件夹 , webpack.config.js 配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    const path = require("path")
    var htmlWebpackPlugin = require('html-webpack-plugin');
    //webpack基于node构建的,所有用的是CommonJS模块化规范
    module.exports = {
    mode:"development",
    entry: path.join(__dirname, './src/main.js'),
    output: {
    path: path.join(__dirname, './dist'),
    filename: 'bundle.js'
    },
    plugins: [
    // 添加plugins节点配置插件
    new htmlWebpackPlugin({
    template:path.resolve(__dirname, 'src/index.html'),//模板路径
    filename:'index.html'//自动生成的HTML文件的名称
    })
    ],
    }
  2. 安装webpack和webpack-cli

    1
    2
    npm install webpack@4.27.1 -d
    npm install webpack-cli -d 提供一些基本命令(比如webpack命令)

    4.index.html

1
2
3
4
5
6
<head>
<meta charset="UTF-8">
<title>Title</title>

<script src="../dist/bundle.js"></script>
</head>
  1. webpack

4.3.配置webpack-dev-serve

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#1.安装webpack-dev-serve
npm install webpack-dev-server -d

#2.package.json的scripts添加dev
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open --port 3000 --hot --host 127.0.0.1"
},
#3.npm run dev webpack-dev-server将打包后的bundle.js托管到项目根路径下(内存中),所以可以通过下面路径访问
http://localhost:8080/bundle.js

#4.修改index.html中引入bundle.js的路径
<head>
<meta charset="UTF-8">
<title>Title</title>

<!--使用webpack-dev-server打包后内存中的bundle.js-->
<script src="../bundle.js"></script>
</head>

4.4. 配置到内存中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#1.安装html-webpack-plugin
npm i html-webpack-plugin@3.2.0 --save-dev

#2.修改webpack.config.js配置 ★☆★☆★☆★
// 导入自动生成HTMl文件的插件 ★☆★☆★☆★
var htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
mode:"development",
entry: path.join(__dirname, './src/main.js'),
output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
},
plugins: [
// 添加plugins节点配置插件
new htmlWebpackPlugin({
template:path.resolve(__dirname, 'src/index.html'),//模板路径
filename:'index.html'//自动生成的HTML文件的名称
})
],
}

5. 遇到问题报错如下

1
webpack-dev-server  不是内部或外部命令,也不是可运行 的程序 或批处理文件。

解决方法:

1
npm i webpack-dev-server -d

6.在 webpack 中使用 react

​ 1.运行 npm install react react-dom -S 安装包

  • react: 专门用于创建组件和虚拟DOM的,同时组件的生命周期都在这个包中

  • react-dom: 专门进行DOM操作的,最主要的应用场景,就是`ReactDOM.render()

    2.在html页面上准备一个容器

1
2
<!-- 容器,将来,使用 React 创建的虚拟DOM元素,都会被渲染到这个指定的容器中 -->
<div id="app"></div>

​ 3.main.js 中引入包

1
2
import React from 'react'                        // 创建组件、虚拟DOM元素,生命周期
import ReactDOM from 'react-dom' // 把创建好的 组件 和 虚拟DOM 放到页面上展示的

​ 4.创建虚拟 dom ,并且渲染到页面上去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React from 'react'                        // 创建组件、虚拟DOM元素,生命周期
import ReactDOM from 'react-dom' // 把创建好的 组件 和 虚拟DOM 放到页面上展示的

// 这是 创建虚拟DOM元素的 API <h1 title="啊,五环" id="myh1">你比四环多一环</h1>
// 第一个参数: 字符串类型的参数,表示要创建的标签的名称
// 第二个参数:对象类型的参数, 表示 创建的元素的属性节点
// 第三个参数: 子节点(包括 其它 虚拟DOM 获取 文本子节点)
// 参数n : 其它子节点


const myh3 = React.createElement('h2',{title:'这是title',id:'myh3'},'这是myh3,下面没有子元素')
const mydiv = React.createElement('div',{className:'color'},'这是一个div1的容器,下面有子元素',myh3)


// 3. 渲染虚拟DOM元素
// 参数1: 表示要渲染的虚拟DOM对象
// 参数2: 指定容器,注意:这里不能直接放 容器元素的Id字符串,需要放一个容器的DOM对象
ReactDOM.render(myh1, document.getElementById('app'))

//class使用 className

7. 虚拟 dom的介绍(提高性能)

React.creatElement()相当于在内存中去构建 dom 。 当页面将要呈现的时候:

1.浏览器会获取整个页面的内容

2.构建dom树 document文档对象 (将页面上的标签,属性,文本转换成 dom 对象)

3.在内存就好像如下的形式:

1
2
3
4
5
6
7
8
9
{
tagName:"div",
attrs:[
{ id : "box"},
{ name : "dongwenbin"}
{ class: ""}
],
children:[]
}

4.新旧的dom进行差异对比,产生出差异dom,更新真实的dom,最后视图的更新

8.JSX 语法

1.jsx语法:是一种符合 xml 规范的js语法 extend markup language 可拓展标记语言

1
2
3
4
1.安装babel:
npm i babel-core@6.26.3 babel-loader@7.1.5 babel-plugin-transform-runtime --save-dev

npm i babel-preset-env babel-preset-stage-0 --save-dev

2.安装能够识别转换jsx语法的包 babel-preset-react

1
npm i babel-preset-react -D

3.添加 .babelrc 文件配置文件如下:

1
2
3
4
{
"presets": ["env", "stage-0", "react"],
"plugins": ["transform-runtime"]
}

4.在 webpack.config.js中添加

1
2
3
4
5
module: { //要打包的第三方模块
rules: [
{ test: /\.js|jsx$/, use: 'babel-loader', exclude: /node_modules/ }
]
}

优点:不仅帮助我们创建虚拟dom,还允许我们在jsx中嵌入js表达式,js语法

缺点:其本质依然是借助React.createElement()来创建虚拟dom

在jsx中嵌入js代码 , 需要用{} , 数组里的 需要 key = “1”

1
2
3
4
5
6
7
8
9
10
11
{arrStr.map((item) => {
return <p key={item}>{item}</p>

})}
//数组的遍历 , 然后转换成指定的内容,也需要key 和 {} 进行才可以。

<label htmlFor="name">label</label>

{/* 注释 */}

只能有一个根标签,所有标签必须闭合

9.组件&Props

  1. 纯函数

    函数内部的代码不会对函数的入参以及函数外部的代码有任何的影响

  2. React 的组件

    2.1 函数组件(纯函数)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import React from 'react'                        // 创建组件、虚拟DOM元素,生命周期
    import ReactDOM from 'react-dom' // 把创建好的 组件 和 虚拟DOM 放到页面上展示的
    //react 中创建组件的第一种方式:使用纯函数
    function Hello(props) {
    console.log(props)
    return <div>{props.name}{props.age}</div>
    }

    export default Hello;
    //导出到外部的main.js中去接收

    2.2//展开运算符{…obj},节省了代码

    1
    2
    3
    ReactDOM.render(<Hello name={obj.name} age={obj.age} gender={obj.gender}></Hello>, document.getElementById('app'));

    ReactDOM.render(<Hello {...obj}></Hello>, document.getElementById('app'));

    2.2 类组件

    2.2.1 react中给我们了一个可以继承的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import React from 'react'
import ReactDOM from 'react-dom'

export default class Movie extends React.Component {
constructor() {
//super()需要是构造函数的第一行代码
super()

//使用class方式创建的组件允许组件有自己的state数据和action
//函数的形式不可以的有自己的数据
this.state = {
msg: '大家好,我是 class 创建的 Movie组件'
}
}

render() {
return <div>{this.state.msg}{this.props.name}</div>
}
}

//静态对象只属于类, 不属于创建new的对象
//静态方法,也是属于类,通过类名直接调用
//继承可以把公共的类放在Animal中 es6
//继承:class Dog extends Anmial
constructor(name,age,gender){
super(name,age);
//super调用父类的方法来初始化成员的信息
//继承的情况下必须使用super在第一行的创建,才可以创建
this.gender = gender;
}
9.1 两种创建的对比
  • 函数组件:又叫无状态组件、木偶组件、非受控组件 (只有props,没有state,没有生命周期钩子函数)
  • Class组件:有状态组件、智能组件、受控组件(有state,有生命周期钩子函数)

10. state 的数据更改问题

借助 this.setState 来修改 ,可以入参两个参数 ;

如果要立刻获取到更改完之后的数据,利用setState()函数指定第二个箭头参数 ,() => {}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 如果我们不基于以前的值来更改当前state的值,我们可以这样下
// this.setState({count:2})

// 如果我们需要根据以前的值来更改当前的state的值,我们可以向下面这样写:
// this.setState((state,props) => ({
// count : ++state.count
// }))

//如果我们想要修改state之后立马获取最新的数据,我们可以给setState()函数指定第二个参数
this.setState((state,props) => ({
count : ++state.count
}),()=>{
console.log(this.state.count)
})

//state的更新可能是异步的!!!!
//state的更新既可能是同步的,也可能是异步的。准确地说,在React内部机制能检测到的地方, setState就是异步的;在React检测不到的地方,例如setInterval,setTimeout里,setState就是同步更新的。”
// setTimeout(() => {
// this.setState({count:2})
// console.log(this.state.count) //因为setState()写在了setTimeout()函数里面,所以现在的setState()就是同步更新的
// }, 1000);
10.1 state 更新的原理
1
2
 setState本质是通过一个队列机制实现state更新的。 执行setState时,会将需要更新的state合并后放入状态队列,而不会立刻更新state,队列机制可以批量更新state。
如果不通过setState而直接修改this.state,那么这个state不会放入状态队列中,下次调用setState时对状态队列进行合并时,会忽略之前直接被修改的state,这样我们就无法合并了,而且实际也没有把你想要的state更新上去。
this.setState(newState)
newState 存入pending 队列 (待定队列)
判断是否处于 batch update (分批更新)
1.保存在 dirtyComponents 中 (Y) 2.遍历dirtyComponents ,调用updateComponent,更新 pending state or props (N)

10.1.1 如何知道已经被更新

  • 回调函数
  • 钩子函数

10.1.2 需要注意的地方

  • setState可能会引发不必要的渲染(renders)
  • setState无法完全掌控应用中所有组件的状态
10.2 updateComponent 中的 diff
(a) tree diff
1
2
3
其实传统diff算法就是对每个节点一一对比,循环遍历所有的子节点,然后判断子节点的更新状态。通过循环递归对节点进行依次对比,算法时间复杂度达到 O(n^3) ,n是树的节点数,这个有多可怕呢?——如果要展示1000个节点,得执行上亿次比较。即便是CPU快能执行30亿条命令,也**很难在一秒内**计算出差异。。

React 通过制定大胆的策略,将 O(n^3) 复杂度的问题转换成 O(n) 复杂度的问题。react根据自己的特点,实现了部分代码的简化。
1
2
那么问题来了,如果DOM节点出现了跨层级操作,diff会咋办呢?
答:diff只简单考虑同层级的节点位置变换,如果是跨层级的话,只有创建节点和删除节点的操作。
(b) component diff
1
2
3
4
React应用是基于组件构建的,对于组件的比较优化侧重于以下几点:
1. 同一类型组件遵从tree diff比较v-dom树
2. 不同类型组件,先将该组件归类为dirty component,替换下整个组件下的所有子节点
3. 同一类型组件Virtual Dom没有变化,React允许开发者使用shouldComponentUpdate()来判断该组件是否进行diff,运用得当可以节省diff计算时间,提升性能
1
如上图,当组件D → 组件G时,diff判断为不同类型的组件,虽然它们的结构相似甚至一样,diff仍然不会比较二者结构,会直接销毁D及其子节点,然后新建一个G相关的子tree,这显然会影响性能,官方虽然认定这种情况极少出现,但是开发中的这种现象造成的影响是非常大的。
(c) element diff
1
2
3
4
对于同一层级的element节点,diff提供了以下3种节点操作:
1. INSERT_MARKUP 插入节点
2. MOVE_EXISING 移动节点
3. REMOVE_NODE 移除节点
1
2
3
一般diff在比较集合[A,B,C,D]和[B,A,D,C]的时候会进行全部对比,即按对应位置逐个比较,发现每个位置对应的元素都有所更新,则把旧集合全部移除,替换成新的集合,如上图,但是这样的操作在React中显然是复杂、低效、影响性能的操作,因为新集合中所有的元素都可以进行复用,无需删除重新创建,耗费性能和内存,只需要移动元素位置即可。

React对这一现象做出了一个高效的策略:允许开发者对同一层级的同组子节点添加唯一key值进行区分。意义就是代码上的一小步,性能上的一大步,甚至是翻天覆地的变化!

#####

八.Git的简单用法

Posted on 2019-11-20

1.秘钥的生成

1
2
3
4
5
6
7
8
9
10
11
#1.打开git brash,输入命令 ssh-keygen -t rsa -C "youremail@example.com"
#2.找到用户主目录下的ssh文件夹,复制id_rsa.pub 文件内容
#3.码云后台点击设置,ssh公钥,黏贴id_rsa.pub 文件内容
#4.码云后台创建新项目
#5.配置本地全局的账号和密码
git config --global user.name "dwbykst"
git config --global user.email "1491749434@qq.com"
#6.关联远程仓库
cd project
git remote add origin git@github.com:dwbskt/myvue.git
git push -u origin master

1.1 如果已经绑定则解除

1
git remote rm origin

理解 :在同一台电脑上的ssh只能绑定一个github ,之后再用git进行操作。

2.上传步骤

1
2
3
4
5
	修改本地代码,再提交的步骤
1 修改代码
2 git add * 将修改的代码提交到暂存区
3 git commit -m “第一次提交” 将暂存区的代码提交到本地库
4 git push 将本地库的代码提交到远程服务器

3.错误 error

vue项目 git提交失败 running pre-commit hook:lint-staged

那就是删除掉pre-commit hook,具体在项目文件夹.git\hooks目录下,找到文件pre-commit

特殊:前端问题持续更新

Posted on 2019-11-16

1. 函数的副作用

vue 中的 setstate 会产生副作用 , 佐证为 watch 监听时里面的属性的改变不会引发监听的事件。

函数的副作用的举例:

  1. 纯函数的副作用 , 通过函数直接改变obj中的属性值,会造成副作用

  2. 以下情况下没有副作用:通过函数的值改变 obj2 的值,再用 obj2 的值来替换 obj 的值 ,这样就不会造成函数的副作用

2. 函数式编程思想(待更新)

React 16.7.0 ——> React 16.8.0 (Hook)

Vue 2.0 ——> Vue 3.0 ( Hook 、Proxy)

1
2
3
 vue中的 proxy代理  ,数据劫持的核心就是在代理对象的身上重新定义被代理对象的所有可枚举属性,并设置 getter 和 setter 监听着它的变化,然而实现这个功能就是一个方法:

Object.defineProperty() ,通过该方法在实例对象上重新定义了和data 对象里面所有的属性,然而就实现了数据劫持。

3. Tomcat服务器的搭建

(1)下载tomcat服务器

https://tomcat.apache.org/download-70.cgi

(2)下载java的jdk、安装

配置环境变量

1
2
3
JAVA_HOME=C:\Java\jdk1.8.0_144
classpath=.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\tools.jar
PATH配置:;%JAVA_HOME%\bin;
(3)解压tomcat,修改里面的server.xml配置
1
2
3
4
5
6
在apache-tomcat-7.0.96-windows-x64—>apache-tomcat-7.0.96—>conf 中

修改如下的代码:
<Connector port = "8090" protocol:"HTTP/1.1"
connectionTimeout = "20000"
redirectPort = "8843" />
(4)启动 tomcat 服务器

4. node中注意的东西

1
2
3
4
5
6
7
8
9
10
__filename : 包含文件名称的全路径
__dirname : 文件所处的目录的绝对路径(不包含文件名称)

//在 node 中没有dom操作和 bom 操作的api , 也就意味着window document 等对象在 node 中不可以使用 , 可以使用如下:
global.console.log("aaa")
global 就是 顶层对象

process.argv argv 是一个数组,默认情况下,前两项的数据分别是:Node.js环境的路径:当前执行的js文件的全路径
// 从第三个参数开始表示命令行参数
process.arch 就是系统的架构,64位或者32位
4.1 stat 和 fstat 的区别

fs.stat 接收的第一个参数是一个文件路径字符串

fs.fstat接收的是一个文件描述符;

内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件

其它的Fs方法中和这种类似的也是这样的描述;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//基于Promise的API的所有方法调用之后都会给我们返回一个promise,然后我们就可以使用.then
fsPromises.stat("./tt")
.then(function(data){
console.log(data)
},function(err){
console.log(err);
return fsPromises.mkdir("./tt");
})
.then(function(data){
console.log(data)
return fsPromises.writeFile("./tt/bb.txt","xxxxx你好");
},function(err){
console.log(err)
})
.then(function(data){
console.log(data);
})

5. e.target.innerHTML

可以获取到 a 标签里的值,不是用value进行获取的。

6. axios 原生的了解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});

params 的传递是根据对象的形式,在发送请求的时候要进行封装成对象的形式。

原生的 axios get请求的形式值得去了解一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const axios = require('axios');

// Make a request for a user with a given ID
axios.get('/user?ID=12345')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.finally(function () {
// always executed
});

友情链接: https://www.npmjs.com/package/axios?activeTab=readme

7. 数组的 … 进行添加

1
2
this.array = [...cdata.message,...this.array]
//数组的叠加

七.vue项目整合问题

Posted on 2019-11-15

一、vue项目整合中遇到的问题

1.1 vuex中插件的使用

1.1.2 插件的功能

插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:

  1. 添加全局方法或者属性。如: vue-custom-element
  2. 添加全局资源:指令/过滤器/过渡等。如 vue-touch
  3. 通过全局混入来添加一些组件选项。如 vue-router
  4. 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
  5. 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//vuex 状态持久化插件 —— vuex-persistedstate
//安装:

  npm install --save vuex-persistedstate

//引用:

  import createPersistedState from 'vuex-persistedstate'

//配置:

  new Vuex.Store({plugins: [createPersistedState()] })

//作用:

  将 vuex 状态保存到 localstorage 中
1.1.3 持久化插件优点

Vuex 解决了多视图之间的数据共享问题。但是运用过程中又带来了一个新的问题是,Vuex 的状态存储并不能持久化。也就是说当你存储在 Vuex 中的 store 里的数据,只要一刷新页面,数据就丢失了。

引入vuex-persist 插件,它就是为 Vuex 持久化存储而生的一个插件。不需要你手动存取 storage ,而是直接将状态保存至 cookie 或者 localStorage 中

1.2图片的懒加载

1
2
3
4
5
6
7
8
<img v-lazy="item.v_pic"  />

/*懒加载的样式*/
img[lazy="loading"] {
width: 40px;
height: 300px;
margin: auto;
}

1.3路由的返回设置

1
2
3
4
reggoback(){
this.$router.go(-1)
//返回上一级的路由
},
  • this.$router.go(val) => 在history记录中前进或者后退val步,当val为0时刷新当前页面。
  • this.$router.push(path) => 在history栈中添加一条新的记录。

六.vue项目实战

Posted on 2019-11-13

1.Vue项目

1.1 初始阶段进行文档的编写

1
2
3
4
5
发布博客。以下的步骤: 
在本地博客文件夹根目录(git bash)输入:
hexo new "6.vue项目实战"
hexo g //生成网页
hexo d //部署到远端(github)

1.2 vue-cli使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1.npm install -g @vue/cli@3.9.1
2.将配置环境变量 C:\dev\nodejs
3.vue create project-name

//查看最终生效的 webpack 配置信息
vue inspect > output.js

//配置文件参考文档
https://cli.vuejs.org/zh/config/#devserver-proxy

//运行App
npm run serve

//编译App
npm run build

1.3 vue-cli 的创建使用选项

1
2
3
4
5
6
7
8
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, CSS Pre-processors, Linter
? Use history mode for router? (Requires proper server setup for index fallback in production) No
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Less
? Pick a linter / formatter config: Basic
? Pick additional lint features: Lint and fix on commit
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No

1.4 将项目托管到 github

1
2
3
4
5
6
7
8
9
10
11
#1.打开git brash,输入命令 ssh-keygen -t rsa -C "youremail@example.com"
#2.找到用户主目录下的ssh文件夹,复制id_rsa.pub 文件内容
#3.码云后台点击设置,ssh公钥,黏贴id_rsa.pub 文件内容
#4.码云后台创建新项目
#5.配置本地全局的账号和密码
git config --global user.name "shenhaieyu"
git config --global user.email "mazg1987@163.com"
#6.关联远程仓库
cd project
git remote add origin git@gitee.com:shenhaieyu/zg-vuecms.git
git push -u origin master

1.5 严格模式的忽略

1
mui.js?01c3:3440 Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

ignore:[‘./lib/mui/js/mui.js’]

1.6 vue中this.$router.push() 传参

(1) . params 传参

1
2
3
4
5
6
7
注意:patams传参 ,路径不能使用path 只能使用name,不然获取不到传的数据

this.$router.push({name: 'dispatch', params: {paicheNo: obj.paicheNo}})

取数据:this.$route.params.paicheNo

this.$route.params.paicheNo

(2) . query传参

1
2
3
4
5
this.$router.push({path: '/transport/dispatch', query: {paicheNo: obj.paicheNo}})

取数据:this.$route.query.paicheNo

this.$route.query.paicheNo

1.7 vuex的基本使用

(1). 基本的使用情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
//state用于存储数据
state: {
},
//里面放的是方法,方法主要用于改变state里面的数据
mutations: {
},
//方法,可以修改mutation
//actions(方法 可以dispatch mutations) actions中可以有异步操作
actions: {
},
modules: {
},
//对外暴露数据,不修改vuex中的数据
getters: {
}
})


//5.修改store中的数据 (参数1:是mutations的名字 参数2:传递给mutations的数据)
this.$store.commit("subtract",{num:3})

(2). vuex的缓存问题

vuex中数据在刷新网页的时候会丢失。解决思路:我们可以将 vuex 中的数据写到 localstorage 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
npm install --save vuex-persistedstate 


//store.js

import createPersistedState from 'vuex-persistedstate'

const store = new Vuex.Store({
state: {
selected_card: {}, //用户选择的银行卡
},
mutations: {
update_selected_card(state, payload) {
state.selected_card = payload
},
},
plugins: [createPersistedState()],
})

1.8 qs.stringify()、qs.parse()的使用

qs可通过npm install qs命令进行安装,是一个npm仓库所管理的包。

而qs.stringify()将对象 序列化成URL的形式,以&进行拼接。

1
2
3
4
5
var a = {name:'hehe',age:10};
qs.stringify(a)
// 'name=hehe&age=10'
JSON.stringify(a)
// '{"name":"hehe","age":10}'

1.9 发送的请求的不同的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import axios from 'axios';
import QS from 'qs';
//设置超时时间
axios.defaults.timeout = 10000;
// post请求头
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';

axios.defaults.baseURL = "http://songshu.xiaomy.net/";

export default function myaxios(method, url, params) {
if (method == "GET") {
return axios.get(url, { params: params });
} else if (method == "POST") {
var params = QS.stringify(params);
return axios.post(url, params);
}
}
1
2
3
4
5
6
7
8
9
10
await myaxios("POST", postusername, this.obj)
.then(data => {
this.userlist = data.data.message;
console.log(this.userlist);
// this.headimg = this.userlist.headimg_url;
this.$store.commit("imgurl",this.headimg);
console.log(this.$store.getters.getimgurl,"22222");
this.headimg = this.$store.getters.getimgurl;
});
},

五.项目的挂载服务器apache

Posted on 2019-11-11

1. 打包运行

1
2
3
4
5
6
7
8
9
npm run build 
//注意在 mui, mui.css 中将所有的 svg 注释掉 , 否则就不会执行的
//需要注意的是我在
//E:\code\11.01\vueapp\node_modules\@intervolga\optimize-cssnano-plugin\index.js
//vueapp\node_modules\@intervolga\optimize-cssnano-plugin\index.js
//注释了105行到107行的代码
hasErrors = true;
throw new Error('CSS minification error: ' + err.message +
'. File: ' + assetName);

2. 打包后在dist中遇到跨域的问题

一开始的跨域是用file的请求发送的

3. Apache 服务器的搭建

3.1 Apache的基础安装

  1. 解压 建议把解压后的文件拷贝到不带中文的路径下

    httpd-2.4.35-win32-VC14.zip

  2. 打开解压后的Apache24目录,找到bin,打开cmd,输入httpd -t 命令,查看错误,如果是在win10 的环境下

    直接使用不可以话,在命令行前面加上 ./

  3. 修改conf下httpd.conf配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    在 Apache24 中 conf 文件夹中改变 httpd.conf

    37 Define SRVROOT "D:/1-igeek 前端/tool/工具/Apache24"
    38 ServerRoot "D:/1-igeek 前端/tool/工具/Apache24"

    59 #Listen 12.34.56.78:80
    60 Listen 8888

    225 #
    226 ServerName localhost:8888

    234 <Directory />
    AllowOverride none
    #Require all denied
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Allow from all
    241 </Directory>

    255 DocumentRoot "E:/1-vueapp"
    256 <Directory "E:/1-vueapp">
  4. 在E:/webapps(存放dist文件的文件夹)中准备一个index.html文件

  5. ​ 输入对应的命令来注册apache服务

    # 安装 Apache 服务,‐n 参数是指定服务名称

    $ httpd.exe -k install -n “Apache”

    # 如果需要卸载 Apache,可以执行以下命令

    $ httpd.exe -k uninstall -n “Apache”

    \2. 启动apache服务器

    $ httpd.exe -k start -n “Apache”

    # 重新启动 Apache 服务

    $ httpd.exe -k restart -n “Apache”

    # 停止 Apache 服务

    $ httpd.exe -k stop -n “Apache”

  6. 在浏览器中输入localhost:8888查看是否有网页显示

3.2 配置Apache虚拟主机

1、修改httpd.conf配置文件

1
2
# Virtual hosts   //508
Include conf/extra/httpd-vhosts.conf //509

2.修改 vhost.conf 文件 (在conf—>extra—>httpd-vhosts文件中)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<VirtualHost *:8888> 
DocumentRoot "E:/webapps1"
ServerName localhost
<Directory "E:/webapps1">
Options FollowSymLinks Indexes
AllowOverride none
Require all granted
</Directory>
</VirtualHost>
解决项目发布之后的跨域问题
配置反向代理:
1、httpd.conf配置文件

2、httpd-vhosts.conf配置
<VirtualHost *:8888>
#绑定域名
ServerName localhost
#默认首页
DirectoryIndex index.html index.php
#指定网站根目录
DocumentRoot "E:/webapps1"
#指定目录分配权限
<Directory "E:/webapps1">
#没有首页就显示列表(开发阶段可以这样)取值:all none Index
Options Indexes
#规定Deny,Allow的执行顺序, Order Deny,Allow : 先执行Deny,再执行Allow
Order Deny,Allow
#全部禁止访问 取值:all none 指定ip
Allow from All
#但是,允许自己访问 取值:all none 指定ip
Allow from all
</Directory>
Proxyrequests off
<Proxy *>
#规定Deny,Allow的执行顺序, Order Deny,Allow : 先执行Deny,再执行Allow
Order Deny,Allow
#全部禁止访问 取值:all none 指定ip
Allow from All
</Proxy>
#配置反向代理
ProxyPass /api http://192.168.23.200:8899/api
</VirtualHost>
//3、打开浏览器就可以访问网站了

3.3 开启apache服务器的gzip压缩:

1.打开 httpd.conf配置文件中下面两个模块的注释

#LoadModule deflate_module modules/mod_deflate.so

#LoadModule headers_module modules/mod_headers.so

2.在httpd.conf配置文件最下面添加

​ SetOutputFilter DEFLATE

​ DeflateCompressionLevel 9

4. 需要注意的一些代理的问题

1
2
3
在 main.js 中如下:
//打包成apk的时候需要打开的
axios.defaults.baseURL = "http://47.103.222.56:8899";
4.1 需要在 vue.config.js 中配置代理
1
2
3
4
5
6
7
8
9
10
proxy: {
//凡是请求以api开头的都会使用下面的代理服务器
'/api/*': {
// target: 'http://bc421114.ngrok.io/',
target: 'http://47.103.222.56/', // 目标服务器地址
secure: false, // 目标服务器地址是否是安全协议
changeOrigin: true, // 是否修改来源, 为true时会让目标服务器以为是webpack-dev-server发出的请求!服务端和服务端的请求是没有跨域的
//pathRewrite: {'^/api': '/a'} // 将/api开头的请求地址, /api 改为 /, 即 /api/xx 改为 /xx
}
}
4.2 在Apache中配置方向代理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<VirtualHost *:8888> 
DocumentRoot "E:/1-vueapp"
ServerName localhost
<Directory "E:/1-vueapp">
Options FollowSymLinks Indexes
AllowOverride none
Require all granted
</Directory>
Proxyrequests off
<Proxy *>
#规定Deny,Allow的执行顺序, Order Deny,Allow : 先执行Deny,再执行Allow
Order Deny,Allow
#全部禁止访问 取值:all none 指定ip
Allow from All
</Proxy>
#配置反向代理
ProxyPass /api http://47.103.222.56:8899/api
</VirtualHost>

在服务器的后台代码中 ,我们注意的是,开放所有的监听的端口为 0.0.0.0

四. Vue中的切换动画

Posted on 2019-09-25

1. 动画的控制以及切换

1
2
3
4
5
<mt-header fixed title="松鼠商城">
<a href="#" v-if="flag" slot="left">
<mt-button icon="back" @click="goBack">返回</mt-button>
</a>
</mt-header>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
watch: {
//控制返回按钮是否需要显示的
"$route.path": function(newVal, oldVal) {
if (
newVal == "/" ||
newVal == "/member" ||
newVal == "/cart" ||
newVal == "/search"
) {
this.flag = false;
} else {
this.flag = true;
}
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//监听路由变化,控制动画的
$route(to, from) {
//定义一个数组,用来规定在什么时候不需要动画的切换
var arr = ["/", "/mumber", "/cart", "/search"];
let isBack = this.isBack;

//如果用户点击了返回按钮,此时用slide-right动画
if (this.isBack == true) {
this.transitionName = "slide-right";
}
//如果用户没有点击返回按钮
else {
//当路由的出发点和目标点在arr数组中,此时不需要动画
if (arr.includes(to.path) && arr.includes(from.path)) {
this.transitionName = "";
}
//当路由不是在'/','/member','/cart','/search' 这些之间跳转的时候,需要slide-left动画
else {
this.transitionName = "slide-left";
}
}
//重置动画的默认状态
this.isBack = false;
}
},
1
2
3
4
5
6
7
methods: {
//当我们点击返回按钮的时候,修改isBack为true
goBack() {
this.isBack = true;
this.$router.go(-1);
}
}

2. 路由的懒加载

1
2
3
4
5
6
7
const Home = () => import('./views/Home.vue')
const Member = () => import('./views/Member.vue')
const Cart = () => import('./views/Cart.vue')

//可以发现变化如下:
//1.打包后的bundle.js文件体积小了
//2.只有打开某个路由之后才会执行该路由对应的组件中的js代码

3. 按需加载 vue/cli中的按需导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
在使用vue/cli脚手架的项目中要实现按需导入:
1.删除babel.config.js文件
2.在项目根目录下创建.babelrc文件
{
"presets": ["@vue/app", ["@babel/preset-env", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "mint-ui",
"style": true
}
]
]
}
3.安装 npm install babel-plugin-component -D 插件

4. 移动端的适配问题

1
2
3
4
5
6
7
8
//1.安装flexible。 flexible主要是实现在各种不同的移动端界面实现一稿搞定所有的设备兼容自适应问题
npm install lib-flexible --save

//2.main.js引入flexible
import 'lib-flexible'

//此时运行程序会看到html中自动加上了font-size font-size的默认值为viewport的十分之一
//在页面中引入flexible.js后,flexible会在<html>标签上增加一个data-dpr属性和font-size样式(如下图)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//1.安装postcss-pxtorem
npm install postcss-pxtorem --save-dev

//2.修改postcss.config.js
module.exports = {
plugins: {
//autoprefixer 自动补全css前缀的东西
'autoprefixer': {
//兼容的机型
browsers: ['Android >= 4.0', 'iOS >= 7']
},
'postcss-pxtorem': {
rootValue: 37.5, //换算基数,一般和html的font-size一致
propList: ['*'] //哪些css属性需要换算
}
}
};
// 以37.5位基准,如下图的1.6rem 就是 60px
1
2
3
4
5
mui-grid-view.mui-grid-9 img[data-v-fae5bece] {

width: 1.6rem;
height: 1.6rem;
}

5. 断点的调试

1
2
config.devtool = '#cheap-module-eval-source-map'
再在需要的地方加上 debugger

三. Vue项目中的结尾调试

Posted on 2019-08-17

1. 动画的控制以及切换

1
2
3
4
5
<mt-header fixed title="松鼠商城">
<a href="#" v-if="flag" slot="left">
<mt-button icon="back" @click="goBack">返回</mt-button>
</a>
</mt-header>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
watch: {
//控制返回按钮是否需要显示的
"$route.path": function(newVal, oldVal) {
if (
newVal == "/" ||
newVal == "/member" ||
newVal == "/cart" ||
newVal == "/search"
) {
this.flag = false;
} else {
this.flag = true;
}
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//监听路由变化,控制动画的
$route(to, from) {
//定义一个数组,用来规定在什么时候不需要动画的切换
var arr = ["/", "/mumber", "/cart", "/search"];
let isBack = this.isBack;

//如果用户点击了返回按钮,此时用slide-right动画
if (this.isBack == true) {
this.transitionName = "slide-right";
}
//如果用户没有点击返回按钮
else {
//当路由的出发点和目标点在arr数组中,此时不需要动画
if (arr.includes(to.path) && arr.includes(from.path)) {
this.transitionName = "";
}
//当路由不是在'/','/member','/cart','/search' 这些之间跳转的时候,需要slide-left动画
else {
this.transitionName = "slide-left";
}
}
//重置动画的默认状态
this.isBack = false;
}
},
1
2
3
4
5
6
7
methods: {
//当我们点击返回按钮的时候,修改isBack为true
goBack() {
this.isBack = true;
this.$router.go(-1);
}
}

2. 路由的懒加载

1
2
3
4
5
6
7
const Home = () => import('./views/Home.vue')
const Member = () => import('./views/Member.vue')
const Cart = () => import('./views/Cart.vue')

//可以发现变化如下:
//1.打包后的bundle.js文件体积小了
//2.只有打开某个路由之后才会执行该路由对应的组件中的js代码

3. 按需加载 vue/cli中的按需导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
在使用vue/cli脚手架的项目中要实现按需导入:
1.删除babel.config.js文件
2.在项目根目录下创建.babelrc文件
{
"presets": ["@vue/app", ["@babel/preset-env", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "mint-ui",
"style": true
}
]
]
}
3.安装 npm install babel-plugin-component -D 插件

4. 移动端的适配问题

1
2
3
4
5
6
7
8
//1.安装flexible。 flexible主要是实现在各种不同的移动端界面实现一稿搞定所有的设备兼容自适应问题
npm install lib-flexible --save

//2.main.js引入flexible
import 'lib-flexible'

//此时运行程序会看到html中自动加上了font-size font-size的默认值为viewport的十分之一
//在页面中引入flexible.js后,flexible会在<html>标签上增加一个data-dpr属性和font-size样式(如下图)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//1.安装postcss-pxtorem
npm install postcss-pxtorem --save-dev

//2.修改postcss.config.js
module.exports = {
plugins: {
//autoprefixer 自动补全css前缀的东西
'autoprefixer': {
//兼容的机型
browsers: ['Android >= 4.0', 'iOS >= 7']
},
'postcss-pxtorem': {
rootValue: 37.5, //换算基数,一般和html的font-size一致
propList: ['*'] //哪些css属性需要换算
}
}
};
// 以37.5位基准,如下图的1.6rem 就是 60px
1
2
3
4
5
mui-grid-view.mui-grid-9 img[data-v-fae5bece] {

width: 1.6rem;
height: 1.6rem;
}

5. 断点的调试

1
2
config.devtool = '#cheap-module-eval-source-map'
再在需要的地方加上 debugger

二. git中遇到remote origin already exists

Posted on 2019-06-15

PS E:\code\11.01\vueapp> git remote add origin git@github.com:YeeeYe/vue.git
fatal: remote origin already exists.
PS E:\code\11.01\vueapp> git remote rm origin
PS E:\code\11.01\vueapp> git remote add origin git@github.com:YeeeYe/vue.git
PS E:\code\11.01\vueapp> git push -u origin master

注意在git 中遇到问题,fatal: remote origin already exists.

直接输入 git remote rm origin 即可,

再输入git remote add origin git@github.com:YeeeYe/vue.git 关联

最后上传:git push -u origin master

​

123

Dong Wenbin

21 posts
© 2020 Dong Wenbin
Powered by Hexo
|
Theme — NexT.Muse v5.1.4