15、电脑相关、移动端基础(术语|长度单位|设备像素|倍图)、vant-ui相关、微信公众平台、微信小程序-目录说明|WXML语法|WXS语法|事件系统|组件|自定义组件|API、uniapp跨端框架-简介|教程|组件|全局文件、postcss.config.js(2750行)

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
附、电脑相关
  (1)查看命令行:win+r; cmd; 确定
  (2)查看电脑配置:win+r; msinfo32; 确定
  (3)windows10系统输入法切换的快捷键设置步骤:至少有2种输入法同时备用
    A、开始-齿轮-时间和语言-语言-中文(简体中国)-选项-(添加键盘-微软拼音-)微软拼音-选项-按键-模式切换
  (4)搜狗输入法的快捷键界面:S图标-更多设置-属性设置-按键
    A、中英切换
    B、系统功能快捷键-系统功能快捷键设置
  (5)广告屏保的位置与删除
    A、重启
    B、此电脑-(上方中间的)查看-显示-隐藏的项目
    C、打开,C:\Users\制造商(NINGMEI)\AppData\Local\Temp
    D、删除该位置下的所有文件
  (6)谷歌截全屏的步骤
    A、F12
    B、ctrl+shift+p
    C、输入full
    D、点击Capture full size screenshot
    另,免费在线网页转图片,https://www.url2pic.com/url2pic/index.html
  (7)postcss-pxtorem,px转rem
 
一、移动端基础
1、移动端的常用术语
  (1)Uni,统一的,读you ni
  (2)IDE,集成开发环境(Integrated Development Environment),如vscode
  (3)SDK,软件开发工具包(Software Development Kit),软件开发时,开发工具的集合,通常由编译器、调试器和应用编程接口组成
  (4)uniCloud,基于serverless的云开发平台,为开发者提供免费服务器,由DCloud(数字天堂)、阿里云、腾讯云三者联合实现
2、移动端的长度单位(vw、vh、vmin、vmax、%、em、rem、dp、pt、rpx、dot、dpi、ppi、Retina)
   附、px,通用长度单位,像素,pixel,/ˈpɪksl/
  (1)通用
    A、vw,viewpoint width,视窗宽度,1vw等于视窗宽度的1%,如width: calc(100vw - 260px);font-size: 5vw;
    B、vh,viewpoint height,视窗高度,1vh等于视窗高度的1%,如height: calc(100vh - 260px);font-size: 5vh;
    C、vmin,vw和vh中较小的那个,font-size: vw,文字在横、竖屏下,大小不一致
    D、vmax,vw和vh中较大的那个,font-size: vmax,文字在横、竖屏下,大小一致
    E、%,相对于父元素的尺寸
    F、em,相对于父字体大小
    G、rem,相对于根字体大小
  (2)专用
    A、dp,Android长度单位,'ppi/160'px;sp,Android字体大小单位
    B、pt,IOS长度单位,'ppi/163'px;自然界的长度单位,1/72英寸,0.35毫米
    C、rpx,微信长度单位,1rpx=1/750的屏宽
  (3)其它
    A、dot,点,印刷品的最小单位
    B、dpi,点密度,每英寸屏幕所包含的点数,Dots per inch
    C、ppi,像素密度,每英寸屏幕所包含的像素数,Pixels per inch
    D、retina display技术,视网膜显示技术,就是像素密度大一些而已
      iPhone6将一个像素点分拆为四个像素进行显示,像素密度提高4倍,达到326ppi,超过人眼能区分的最大像素密度300ppi
      //简单说就是,一个物理像素占位面积小一点,单位面积物理像素多一点;用pxtorem后,字体占位面积不变,但因包含像素多,因而更清晰=====文字、图片=====
   附、rem,示例
    <style>
      //根字体定义一
      html { font-size: 20px; }
      //根字体定义二
      :root { font-size: 20px; }
    </style>
    <script>
      //根字体定义三
      var designWidth = 1000 ;
      document.documentElement.style.fontSize = document.documentElement.clientWidth/designWidth+"px";
      //代码尺寸为1rem,对应设计稿尺寸为1px
    </script>
    //postcss.config.js里的相关配置
    require('postcss-pxtorem')({//px转rem
      rootValue: 37.5, //对应设计图宽度375px
      propList: ['*'], //将哪些属性的px值转换
    })
3、物理像素比
  (1)像素,显示屏图像或CSS图像的最小单位,单位是px,包含
    A、物理像素
    B、逻辑像素
  (2)物理像素,也叫设备像素,显示屏的最小可控制单元
    附、分辨率,纵横方向的物理像素点数
      A、1K显示屏(分辨率,1920*1080)
      B、2K显示屏(分辨率,2560*1440)
      C、4K显示屏(分辨率,3840*2160)
  (3)逻辑像素,也叫CSS像素,CSS的最小可控制单元,正常情况下,1个物理像素显示1个逻辑像素
  (4)物理像素比,也叫设备像素比(window.devicePixelRatio),物理像素/逻辑像素,含义是几个物理像素显示1个逻辑像素
    A、公司4K、21.5寸屏幕,1个物理像素小,缩放设为200%,2个物理像素显示1个逻辑像素;媒体查询2k,左300,右970,中间剩余像素
    B、住处4K、43.0寸屏幕,1个物理像素大,缩放设为100%,1个物理像素显示1个逻辑像素;媒体查询4k,左200,右485,中间剩余像素
    C、综合分辨率、尺寸、缩放后,上面两者字体大小一样
    D、console.log(window.devicePixelRatio)
4、倍图(是正常像素密度的几倍,就用几倍图)
  (1)正常情况下的对应关系
    A、一倍图:设计稿1,宽度750*1px;分辨率1,x*y
    B、二倍图:设计稿2,宽度750*2px;分辨率2,2x*2y
    C、三倍图:设计稿3,宽度750*3px;分辨率3,3x*3y
    D、四倍图:设计稿4,宽度750*4px;分辨率4,4x*4y,如iPhone6,其物理像素比为1,
  (2)真实项目:一张设计稿3,适配分辨率1、分辨率2、分辨率3、的显示屏,
    A、处理方案1,给1种分辨率写1套代码,先判断屏幕分辨率,再导入代码
      分辨率1显示屏的div宽高用设计稿尺寸的1/3,背景图片用设计稿原图片尺寸的100%填充
      分辨率2显示屏的div宽高用设计稿尺寸的2/3,背景图片用设计稿原图片尺寸的100%填充
      分辨率3显示屏的div宽高用设计稿尺寸的3/3,背景图片用设计稿原图片尺寸的100%填充
    B、处理方案2,以px为单位,用postcss-pxtorem把px转换成rem,使各种分辨率,如安卓、IOS的屏幕,显示相同效果
      div宽高用设计稿尺寸的1/3,背景图片用设计稿原图片尺寸的100%填充
    附、代码,背景图片用设计稿原图片尺寸的100%填充,//=====文字、图片=====
      //下面,设计稿1的图片放在分辨率1的显示屏上,效果是1个逻辑像素被放到1个物理像素里显示;像素密度不变,正常显示
      //下面,设计稿2的图片放在分辨率1的显示屏上,效果是4个逻辑像素被压缩到1个物理像素里显示;像素密度不变,正常显示
      //下面,设计稿2的图片放在分辨率2的显示屏上,效果是1个逻辑像素被放到1个物理像素里显示;像素密度变大,高清显示
      background-image: url(example@2x.png) no-repeat;
      background-size: 100% auto;
5、特别注意
  (1)移动端项目
    A、各个页面的跳转关系
    B、数据临时存储与清除
    C、静态数据的来源(设计稿或后台)
  (2)存储临时数据,以备后退时使用
    A、确定时,用localStorage存储数据
    B、后退时,用localStorage获取数据
    C、提交后,用localStorage删除数据
    D、也可以用vuex存储、获取、删除数据
  (3)iPhone12pro max,跳到新网页,新网页的位置没到顶
    A、原因:跳转前的网页没到顶,浏览器把前网页的位置用在后网页上
    B、解决:document.body.scrollTop=0; document.documentElement.scrollTop=0;
 
二、vant-ui相关
1、<input type="value">
  (1)button,定义可点击按钮(多数情况下,用于通过 JavaScript 启动脚本)
  (2)checkbox,定义复选框
  (3)file,定义输入字段和 "浏览"按钮,供文件上传
  (4)hidden,定义隐藏的输入字段,发送表单的时候,隐藏域的信息也被一起发送到服务器,
    https://blog.csdn.net/weixin_38098192/article/details/90265302
  (5)image,定义图像形式的提交按钮
  (6)password,定义密码字段,该字段中的字符被掩码
  (7)radio,定义单选按钮
  (8)reset,定义重置按钮,重置按钮会清除表单中的所有数据
  (9)submit,定义提交按钮,提交按钮会把表单数据发送到服务器
  (10)text,定义单行的输入字段,用户可在其中输入文本,默认宽度为20个字符
2、深度选择器
  当<style scoped>只作用于当前组件中的元素,可采用下列方式影响到子组件
  附、全局样式
    <style>
      .wrap .child {
        color: red;
      }
    </style>
  (1)本页样式 >>> ,原生css支持,sass/less可能无法识别
    <style scoped>
      .wrap >>> .child {
        color: red;
      }
    </style>
  (2)本页样式 /deep/ ,sass/less可识别,在vue 3.0会报错
    <style scoped>
      .wrap /deep/ .child {
        color: red;
      }
    </style>
  (3)本页样式 ::v-deep ,vue 3.0支持,编译速度快
    <style scoped>
      .wrap ::v-deep .child {
        color: red;
      }
    </style>
3、vant-ui动态内容
  (1)notify 消息提示,没有遮罩,页面顶部显示,有样式变化,3秒后自动消失
  (2)toast 轻提示,没有遮罩,页面居中显示,无样式变化,3秒后自动消失
  (3)NoticeBar 通知栏,没有遮罩,固定位置显示,有样式变化,不消失
  (4)Popover 气泡弹出框,没有遮罩,点击处显示,会基于reference插槽的内容进行定位,常用于下拉选项,
  (5)overlay 遮罩层,全屏罩住
  (6)popup 弹出层,有遮罩,常用触底显示,确认后消失,常用于省市县、日期选择
  (7)dialog 弹出框,有遮罩,常用居中显示,确认后消失
4、van-field
  (1)输入框,正常
  (2)文本框,type="textarea"
  (3)下拉框的逻辑
    输入框禁用,右侧添加三角,
    点击事件让下方气泡popup出现、传出序号、计算-从总数据中找出的相关数据-成下拉选项,
    点击事件从自身数据中找出的相关数据-成为下拉选项,气泡popup出现
    点击确定时,给对应的v-model赋值,气泡消失
  (4)其它,用input插槽,
    自定义输入框,使用此插槽后,与输入框相关的属性和事件将失效
    在Form组件进行表单校验时,会使用input插槽中子组件的value,而不是Field组件的value
  (5)<van-uploader/>的部分属性
    capture,图片选取模式,可选值为camera,直接调起摄像头
    after-read,文件读取完成后的回调函数
    before-read,文件读取前的回调函数,返回false可终止文件读取,支持返回Promise
4、Rule数据结构,只有一个对象项的数组
  (1)required,是否为必选字段,boolean
  (2)message,错误提示文案
  (3)trigger,本项规则的触发时机,可选值为onChange、onBlur
  (4)formatter,格式化函数,将表单项的值转换后,再用“pattern”或“validator”进行校验
  (5)pattern,通过正则表达式进行校验,返回值为false时,红色的message出现在输入框的下方
  (6)validator,通过函数进行校验,返回值为false时,机制让红色的message出现在输入框的下方;
    返回值为promise实例时,机制向其注入resolve、reject,在reject里让红色的message出现在输入框的下方
    validator:function(rule, val, callback) {
      return new Promise(function(resolve, reject) {
        setTimeout(function() {
          const dataNum = Date.now()
          if (dataNum % 2 === 0) {
            resolve('成功')
          } else {
            reject('失败')
          }
        }, 2000)
      })
    }
5、插槽input示例
(1)html部分
  <van-form @submit="beforeSubmit" ref="form">
    <template v-for="(item,idx) in formList">
      <div class="sign-form" :key="idx" v-if="item.inputType == 0">
        <van-field name="name" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" show-word-limit
              :label="item.topicName" v-model="formData[idx]" :placeholder="'请输入'+item.topicName" :maxlength="item.numLimit" />
      </div>
      <div class="sign-form" :key="idx" v-if="item.inputType == 1">
        <van-field rows="4" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" autosize
              v-model="formData[idx]" :label="item.topicName" type="textarea" show-word-limit />
      </div>
      <div class="sign-form" :key="idx" v-if="item.inputType == 2">
        <van-field :label="item.topicName" v-model="formData[idx]" right-icon="arrow-down" readonly placeholder="请选择"
              :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" @click="changeCol(idx)" />
      </div>
      <div class="sign-form" :key="idx" v-if="item.inputType == 3 && item.isCheckbox == 0">
        <van-field :label="item.topicName" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]">
          <template #input>
            <van-radio-group v-model="formData[idx]" direction="horizontal" class="hor-style">
              <van-radio v-for="(v,k) in JSON.parse(item.optionInfo)" :name="v.option" :key="k">{{v.option}}</van-radio>
            </van-radio-group>
          </template>
        </van-field>
      </div>
      <div class="sign-form" :key="idx" v-if="item.inputType == 3 && item.isCheckbox == 1">
        <van-field :label="item.topicName" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]">
          <template #input>
            <van-checkbox-group v-model="formData[idx]" :max="item.selectLimitMax ? item.selectLimitMax : 0" direction="horizontal">
              <van-checkbox v-for="(value,key) in JSON.parse(item.optionInfo)" :name="value.option" shape="square" :key="key">{{value.option}}</van-checkbox>
            </van-checkbox-group>
          </template>
        </van-field>
      </div>
      <div class="sign-form" :key="idx" v-if="item.inputType == 4">
        <div class="van-form_card">
          <div class="field__label">{{item.topicName}}</div>
          <div class="field__desc">支持“图片”扩展名:png、gif、jpeg、pcx、psd、tiff</div>
        </div>
        <van-field name="name" type="hidden" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" v-model="formData[idx]">
          <template #input>
            <div class="upload-preview">
              <van-image v-if="formData[idx]" width="4rem" height="3rem" fit="contain" :src="formData[idx]" />
              <van-uploader :before-read="uploadFile" accept="image/png,image/gif,image/jpeg,image/pcx,image/psd,image/tiff" :name="idx">
                <van-icon name="plus" />
              </van-uploader>
            </div>
          </template>
        </van-field>
      </div>
      <div class="sign-form" :key="idx" v-if="item.inputType == 5">
        <div class="van-form_card">
          <div class="field__label">{{item.topicName}}</div>
          <div class="field__desc">支持“视频”扩展名:avi、MP4、rmvb</div>
        </div>
        <van-field name="name" type="hidden" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" v-model="formData[idx]">
          <template #input>
            <div class="flex-col">
              <div class="video-upload" v-if="showUpload">
                <span>视频上传中...</span>
                <van-progress :show-pivot="false" :percentage="videoUploadPercent" />
              </div>
              <span class="link" v-if="formData[idx]" @click="href(idx)">{{videoName[idx]}}</span>
              <van-uploader :before-read="uploadVideo" accept="*" v-if="!showUpload" :name="idx">
                <van-button icon="plus" type="primary">上传视频</van-button>
              </van-uploader>
            </div>
          </template>
        </van-field>
      </div>
      <div class="sign-form" :key="idx" v-if="item.inputType == 6">
        <div class="van-form_card">
          <div class="field__label">{{item.topicName}}</div>
          <div class="field__desc">支持“文件”扩展名:doc、docx、txt、pdf、pptx、ppt、xlsx、xls</div>
        </div>
        <van-field name="name" type="hidden" :rules="[{ validator: valiFormData, message: '请选择',index:idx }]" v-model="formData[idx]">
          <template #input>
            <div class="flex-col">
              <span class="link" v-if="formData[idx]" @click="href(idx)">{{formData[idx]}}</span>
              <van-uploader :before-read="uploadFile" accept=".doc, .docx, .txt, .pdf, .pptx, .ppt, .xlsx, .xls" :name="idx">
                <van-button icon="plus" type="primary">上传文档</van-button>
              </van-uploader>
            </div>
          </template>
        </van-field>
      </div>
      <div class="sign-form" :key="idx" v-if="item.inputType == 7">
        <van-field readonly @click="clickDatePicker(idx)" name="name" :rules="[{ validator: valiFormData, message: '请选择日期',index:idx }]"
              :label="item.topicName" v-model="formData[idx]" :placeholder="'请选择'+item.topicName" />
        <van-popup v-model="showDatePicker" position="bottom">
          <van-picker
                show-toolbar
                title="选择日期"
                :columns="dateCol"
                @cancel="showDatePicker = false"
                @confirm="dateConfirm" />
        </van-popup>
        <!-- van-popup默认在兄级加蒙层van-overlay,若没有出现,可能有人在项目的全局给清除了 -->
      </div>
    </template>
    <div class="vt-foot ">
      <van-button :loading="loading" loading-text="保存中..." native-type="submit" block color="#fdb235">提交</van-button>
      <!-- native-type,原生button标签的type属性,表单内点击此按钮,自动触发表单的onsubmit事件 -->
      <!-- loading,设置按钮为加载状态,加载状态下默认会隐藏按钮文字 -->
      <!-- loading-text,设置加载状态下的文字 -->
    </div>
  </van-form>
(2)js部分
  A、上传图片
    uploadFile(file, detail) {
      let formData = new FormData();
      formData.append('file', file);
      axios.post(this.$upload, formData, {
        'Content-Type': 'multipart/form-data'
      })
      .then(res => {
        if (res.data && res.data.code === 10000) {
          this.formData[detail.name] = res.data.data;
          let temp = res.data.data;
          this.formData.splice(detail.name, 1, temp);
        } else {
          this.$dialog.alert({
            title: '提示',
            message: '上传文件失败',
            theme: 'round-button',
          })
          .then(() => {
            //on close
          });
        }
      })
    },
  B、上传视频
  来源,https://help.aliyun.com/document_detail/383952.html
    import OSS from "ali-oss";
    //开放存储服务(OpenStorageService,简称OSS),是阿里云对外提供的海量,安全,低成本,高可靠的云存储服务。
    //用户可以通过简单的API(REST方式的接口),在任何时间、任何地点、任何互联网设备上进行数据上传和下载。
    <van-uploader accept="*" v-if="!showUpload"  :name="idx"  :before-read="uploadVideo">
      <van-button icon="plus" type="primary">上传视频</van-button>
    </van-uploader>
    uploadVideo(file, detail) {
      let type = file.name.substring(file.name.lastIndexOf(".") + 1)
        .toLowerCase()
      if (this.videoType.indexOf(type) < 0 || file.type.indexOf("video") < 0) {
        this.$dialog.alert({
          title: '提示',
          message: '仅支持 .avi, .mp4, .rmvb, .mov 格式的视频',
          theme: 'round-button',
        });
        return;
      }
      let max = 1024 * 1024 * 1024;
      if (file.size > max) {
        this.$dialog.alert({
          title: '提示',
          message: '上传视频大小不能超过 1G!',
          theme: 'round-button',
        })
        .then(() => {});
        return;
      }
      myRequest({
          tokenName: "ios",
        })
        .then(data => {
          let client = new OSS({
            region: "oss-cn-beijing",
            accessKeyId: data.data.data.accessKeyId,
            accessKeySecret: data.data.data.accessKeySecret,
            bucket: data.data.data.bucketName,
            stsToken: data.data.data.securityToken,
          });
          const suffix = file.name.substr(file.name.indexOf("."));
          let fileUrl = `test/${new Date().getTime()}${suffix}`;
          client
            .multipartUpload(fileUrl, file, {
              progress: (p) => {
                this.videoUploadPercent = Math.round(p * 100);
                this.showUpload = true;
              },
              partSize: 102400,
            })
            .then((res) => {
              this.showUpload = false;
              this.videoName[detail.name] = res.name;
              let url = res.res.requestUrls[0];
              this.formData[detail.name] = url.substring(0, url.indexOf("?"));
              let temp = this.formData[detail.name];
              this.formData.splice(detail.name, 1, temp);
 
            })
            .catch((err) => {
              this.showUpload = false;
              console.log(err);
              this.$dialog.alert({
                title: '提示',
                message: '上传失败',
                theme: 'round-button',
              })
            });
        })
    }
 
三、微信公众平台账号
 附、简称
  A、“微信账号”简称“微信号”
  B、“微信公众平台账号”简称“平台号”
1、重要网址
  (1)开发
    A、开发文档,https://developers.weixin.qq.com/miniprogram/dev/framework/
    B、开发者工具,https://developers.weixin.qq.com/miniprogram/dev/devtools/devtools.html
    C、开通微信开发者.代码管理,https://developers.weixin.qq.com/miniprogram/dev/devtools/wechatvcs.html
  (2)注册、登录、git仓库
    A、注册网址,https://mp.weixin.qq.com/
      微信十种产品,https://developers.weixin.qq.com/doc/
      四种微信公众号,https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN,
      小程序发布流程,https://mp.weixin.qq.com/wxamp/home/guide?token=1509394140
    B、登录网址,https://mp.weixin.qq.com/
      管理后台,https://mp.weixin.qq.com/wxamp/home/guide
      开发版本,https://mp.weixin.qq.com/wxamp/wacodepage/getcodepage
    C、git仓库网址,https://git.weixin.qq.com/
      四种微信公众号的任意1种账号注册成功,都会生成该仓库网址,该仓库与微信号关联,不会随公众号注销而注销
2、四种微信公众号
   附、四种微信公众号网址,https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN,
  (1)订阅号
  (2)服务号
  (3)小程序(微信小程序-后面详细介绍)
  (4)企业微信(原企业号)
3、微信公众号账号注册
   附、注册网址,https://mp.weixin.qq.com/
  (1)点击“立即注册”
  (2)点击“4种类型中的1种”
  (3)如果点击的是“小程序”,那么还需要在跳转后的页面点击“前往注册”
  (4)填写邮箱、密码、验证码、勾选同意、点击注册,
    A、每个邮箱仅能申请一个小程序==========非常重要===========
    B、作为登录账号,请填写未被微信公众平台注册,未被微信开放平台注册,未被个人微信号绑定的邮箱
  (5)点击登录邮箱、登录邮箱、点击邮箱里的链接
    A、注册国家/地区:中国大陆;主体类型:个人;
    B、身份证姓名、身份证号码、管理员手机号码、短信验证码、管理员身份验证(微信扫一扫)、继续,其中微信扫一扫
      把微信号与微信小程序号关联起来
      1个微信号能关联5个公众号==========非常重要===========
    C、请确认以下提交的主体信息、确定
    D、信息提交成功,前往小程序(管理后台),见7
4、小程序账号注销
   附、登录网址,https://mp.weixin.qq.com/
  (1)登录小程序的管理员账号
  (2)如果提示该账号已冻结,则根据提示进行解冻
  (3)如果尚无AppID(小程序ID),则需要先进行“AppID生成”
  (4)管理后台-点击(左下方)“设置”-点击(页面中间)“账号信息”里的“账号注销”按钮,(微信号的)公众平台安全助手-收到注销信息
  (5)0-6*24小时内,可以电脑登录,取消注销
  (6)6*24--14*24小时之间,可以电脑登录,取消注销或确认注销,逾期不确认账号将恢复正常,
  (7)如果不取消注销或确认注销,那么从
    7*24小时开始,每隔24小时,在-微信号的公众平台安全助手,都会收到注销确认信息,直到取消注销或确认注销或达到7次
  (8)确认注销后,微信扫一扫登录,不再出现该账号
5、小程序账号的作用
  (1)生成(小程序)管理后台
    A、管理项目版本,管理开发者
    B、1个小程序账号,其管理后台只能存储1个小程序项目的3个版本,供发布
  (2)生成存储仓库
    A、存储项目代码
    B、1个小程序账号,其git仓库能存储多个小程序项目的代码,供开发
6、小程序开发者工具的作用
  (1)把小程序体验版-存储到管理后台
  (2)把小程序代码-存储到git仓库
   附、开发小程序
    A、搜索,点击放大镜图标或者ctrl+shift+f
    B、编辑,点击文件图标
7、小程序管理后台-目录
   附、登录网址,https://mp.weixin.qq.com/
   附、管理后台网址,https://mp.weixin.qq.com/wxamp/home/guide
  (1)小程序账号登录,下面两种登录任选一种
    A、使用账号登录,邮箱/微信号
    B、微信扫一扫登录,扫后会出现该微信号关联的所有公众号,点击其中一个(登录)
  (2)登录成功,前往小程序(管理后台),其导航如下
  (3)首页
    A、小程序信息
      未填写//1/3,此处可生成AppID(小程序ID)
      补充小程序的基本信息,如名称、图标、描述等
    B、小程序类目
      未补充
      补充小程序的服务类目,设置主营类目
    C、小程序备案
      未备案
      需先填写小程序信息和类目
      补充小程序的备案信息,检测是否满足备案条件
    D、微信认证
      未完善
      完成微信认证后,账号可获得“被搜索”和“被分享”能力。未完成微信认证不影响后续版本发布
    E、小程序开发与管理
      自己开发
        开发工具
        添加开发者==========非常重要===========
      找服务商开发
        立即前往(按钮)
  (4)管理
    A、版本管理
      线上版本:尚未提交线上版本
      审核版本:你暂无提交审核的版本或者版本已发布上线
      开发版本:你尚未上传任何开发版本,可前往开发者工具上传代码。查看介绍,
      开发版本:版本号;版本信息;提交审核,下拉(选为体验版本,删除);点击“提交审核/选为体验版本/删除”
    B、成员管理==========非常重要=========== 
  (5)开发
    A、开发管理
      开发设置
        开发者ID
          开发者ID,操作
          AppID(小程序ID),wxd9d363f25a//2/3,此处可生成AppID(小程序ID) 
          AppSecret(小程序密钥),生成
        小程序代码上传,开发者可基于配置信息调用微信开发者工具提供的代码上传模块。查看详情
          配置信息,操作
          小程序代码上传密钥,生成
          IP白名单,暂无IP白名单,编辑
        服务器域名(以下略)
      接口设置 
    B、开发工具
  (6)设置
    A、基本设置
      基本信息
      账号信息
        AppID(小程序ID),wxd9d363f25a//3/3,此处可生成AppID(小程序ID)
        登录邮箱
    B、第三方设置
8、小程序管理后台-小程序项目-从创建到保存
  //以下操作位置:微信开发者工具
  (1)创建
    A、首次创建,点击(左上方)项目-扫描二维码-确认登录
    B、再次创建,点击(左上方)项目-新建项目/导入项目
  (2)填写AppID,
    附、以下是AppID生成与获取步骤,任选其一
      A、小程序管理后台-首页-小程序信息
      B、小程序管理后台-开发-开发管理-开发设置-开发者ID
      C、小程序管理后台-设置-基本设置-账号信息 
  (3)勾选用户协议
  (4)其它默认
  (5)确定
  (6)编辑文件
  (7)保存(ctrl+s)
9、小程序管理后台-小程序项目-生成版本
  //以下操作位置:微信开发者工具
  (1)上传项目
    A、首次,点击(右上方)上传按钮。上传成功后,需要联系管理员在小程序管理后台将本次上传“设置为体验版本”。确定
    B、再次,点击(右上方)上传按钮。上次提交已被选为体验版,本次上传将会覆盖体验版,是否继续?确定
  (2)填写版本号、项目备注
  (3)点击上传
  (4)上传成功、确定
  //以下操作位置:管理后台。管理-管理版本-开发版本
   附、管理后台网址,https://mp.weixin.qq.com/wxamp/home/guide
  (5)设置为体验版本
    A、左,版本号
    B、中,版本信息
    C、右,提交审核,选为体验版本、删除
    D、点击选为体验版本,体验版设置,点击提交,(点击下载二维码)扫描二维码体验体验版,前往体验,手动关闭弹窗
10、存储仓库-目录
  附、git仓库网址,https://git.weixin.qq.com/
  (1)项目
    A、您的项目
    B、关注的项目
    C、标星的项目
    D、受邀请项目
  (2)动态
  (3)项目组
  (4)里程碑
  (5)缺陷
  (6)合并请求
  (7)代码评审
  (8)个人设置
11、存储仓库-存储小程序代码
  附、git仓库网址,https://git.weixin.qq.com/
  //以下操作位置:代码仓库
  (1)进入git仓库
  (2)点击创建项目,填写信息,点击创建项目
  //以下操作位置:微信开发者工具/本地磁盘的文件夹
  (3)配置-Git全局设置。首次创建项目,需执行下列命令。以后创建项目,也会出现下列提示,且配置都相同,但无需执行
    git config --global user.name "Z_码农_钱成"
    git config --global user.email "oncw7ZtkhVxE@git.weixin.qq.com"
  (4)拉取-别人正在开发的项目代码,协助别人开发。创建一个新的版本库
    git clone https://git.weixin.qq.com/13718/xiangmuzu1.git
    cd xiangmuzu1
    touch README.md
    git add README.md
    git commit -m "add README"
    git push -u origin master
  (5)推送-自己正在开发的项目代码,让别人协助开发。现有的文件夹或Git版本库
    cd existing_folder
    git init
    git remote add origin https://git.weixin.qq.com/13718/xiangmuzu1.git
    git add .
    git commit -m'自定义'
    git push -u origin master 
  //以下操作位置:微信开发者工具
  (6)推送-拉取别人后推送/再次推送自己
    A、点击(顶部中间左侧)V形符号
    B、点击(顶部中间右侧)...符号
    C、点击commit
    D、点击push
12、存储仓库-删除小程序代码
  附、git仓库网址,https://git.weixin.qq.com/
  //以下操作位置:代码仓库
  (1)进入git仓库
  (2)点击“您的项目/关注的项目/标星的项目/受邀请项目”
  (3)点击某一项目
  (4)点击(左下方)设置
  (5)点击(右中间)去更改可见性级别
  (6)下拉(至最下方),点击删除项目
  (7)输入url,点击确定
 
四、微信小程序-目录说明
 来源,https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html
 来源,https://developers.weixin.qq.com/miniprogram/dev/framework/structure.html
附、目录结构
  ├── app.js
  ├── app.json
  ├── app.wxss
  ├── pages
  │   │── index
  │   │   ├── index.wxml
  │   │   ├── index.js
  │   │   ├── index.json
  │   │   └── index.wxss
  │   └── logs
  │       ├── logs.wxml
  │       └── logs.js
  └── utils
1、 全局配置,一个小程序主体由三个文件组成,必须放在项目的根目录
  (1)app.js,小程序全局逻辑
    App({ //注册小程序。接受一个 Object 参数,其指定小程序的生命周期回调等
      onLaunch: function () {},//生命周期回调——监听小程序初始化
      onShow: function () {},//生命周期回调——监听小程序启动或切前台
      onHide: function () {},//生命周期回调——监听小程序切后台。
      onError: function () {},//错误监听函数。
      onPageNotFound: function () {},//页面不存在监听函数。
      onUnhandledRejection: function () {},//未处理的 Promise 拒绝事件监听函数。
      onThemeChange: function () {},//监听系统主题变化
      其他: 任意类型,开发者可以添加任意的函数或数据变量到参数中,用this可以访问
    })
    附、其它页面,获取实例
    // other.js
      var appInstance = getApp()
      console.log(appInstance.globalData) // I am global data
  (2)app.json,小程序全局配置
    {
      "pages": ["pages/index/index", "pages/logs/index"], //小程序的所有页面
      "requiredBackgroundModes": ["audio", "location"],
      "requiredPrivateInfos": [
        "getLocation",
        "onLocationChange",
        "startLocationUpdateBackground"
        "chooseAddress"
      ],
      "permission": {
        "scope.userLocation": {
          "desc": "你的位置信息将用于小程序位置接口的效果展示" //高速公路行驶持续后台定位
        }
      },
      "window": {
        "navigationBarTitleText": "Demo"
      },
      "tabBar": {
        "height": "50px",
        "fontSize": "10px",
        "list": [
          {
            "pagePath": "pages/index/index",
            "text": "首页"
          },
          {
            "pagePath": "pages/logs/logs",
            "text": "日志"
          }
        ]
      },
      "networkTimeout": {
        "request": 10000,
        "downloadFile": 10000
      },
      "plugins": { //在app.json中声明需要使用的插件
        "myPlugin": {
          "version": "1.0.0",
          "provider": "wxidxxxxxxxxxxxxxxxx"
        }
      },
      "debug": true,
      "resizable": true, //iPad上启用屏幕旋转支持
    }
  (3)app.wxss,小程序全局样式表
2、页面配置,一个小程序页面由四个文件组成
  (1)index.js,页面逻辑
    page({//组件逻辑用Component({})
      data: {},
      options: {},
      behaviors: String/Array,类似于mixins和traits的组件间代码复用机制,
      onLoad: function () {},
      onShow: function () {},
      onReady: function () {},
      onHide: function () {},
      onUnload: function () {},
      onRouteDone: function () {},
      onPullDownRefresh: function () {},
      onReachBottom: function () {},
      onShareAppMessage: function () {},
      onShareTimeline: function () {},
      onAddToFavorites: function () {},
      onPageScroll: function () {},
      onResize(res) { //屏幕旋转事件
        res.size.windowWidth //新的显示区域宽度
        res.size.windowHeight //新的显示区域高度
      },
      onTabItemTap: function () {},
      onSaweexitState: function () {},
      onShow: function () {},
      //其他: 任意类型,开发者可以添加任意的函数或数据变量到参数中,
      //在页面的函数中用this可以访问,这部分属性会在页面实例创建时进行一次深拷贝
      tapName: function(event) {
        console.log(event)
      }
    })
    附、getCurrentPages,获取当前页面栈,数组中第一个元素为首页,最后一个元素为当前页面
    附、Router,页面路由器对象,可以通过this.pageRouter或this.router获得当前页面或自定义组件的路由器对象
  (2)index.json,页面配置
    {
      "navigationBarBackgroundColor": "#ffffff",
      "navigationBarTextStyle": "black",
      "navigationBarTitleText": "微信接口功能演示",
      "backgroundColor": "#eeeeee",
      "backgroundTextStyle": "light"
      "pageOrientation": "auto", //手机单页面启用屏幕旋转支持
    }
  (3)index.wxss,页面样式表
  (4)index.wxml,页面结构
 
五、微信小程序-WXML语法参考
 附、是一套标签语言,结合基础组件、事件系统,可以构建出页面的结构
1、数据绑定,使用Mustache语法(双大括号)将变量包起来
  (1)简单绑定
    <view> {{ message }} </view>
  (2)组件属性
    <view id="item-{{id}}"> </view>
  (3)控制属性
    <view wx:if="{{condition}}"> </view>
  (4)关键字
    <checkbox checked="{{false}}"> </checkbox>
  (5)三元运算
    <view hidden="{{flag ? true : false}}"> Hidden </view>
  (6)算数运算
    <view> {{a + b}} + {{c}} + d </view>
  (7)逻辑判断
    <view wx:if="{{length > 5}}"> </view>
  (8)字符串运算
    <view>{{"hello" + name}}</view>
  (9)数据路径运算
    <view>{{object.key}} {{array[0]}}</view>
  (10)组合数组
    <view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>
  (11)组合对象
    <template is="objectCombine" data="{{for: a, bar: b}}"></template>
  (12)组合对象,后面覆盖前面
    <template is="objectCombine" data="{{...obj1, ...obj2, a: 5}}"></template>
  (13)组合对象
    <template is="objectCombine" data="{{foo, bar}}"></template>
  (14)花括号和引号之间如果有空格,将最终被解析成为字符串
    <view wx:for="{{[1,2,3]}} ">
      {{item}}
    </view> //等同于
    <view wx:for="{{[1,2,3] + ' '}}">
      {{item}}
    </view>
  (15)当wx:for的值为字符串时,会将字符串解析成字符串数组
    <view wx:for="array">
      {{item}}
    </view> //等同于
    <view wx:for="{{['a','r','r','a','y']}}">
      {{item}}
    </view>
  (16)data
    Page({
      data: {
        message: 'Hello MINA!',
        id: 0,
        condition: true,
        a: 1,
        b: 2,
        c: 3,
        name: 'MINA',
        object: {
          key: 'Hello '
        },
        array: ['MINA'],
        zero: 0,
        obj1: {
          a: 1,
          b: 2
        },
        obj2: {
          c: 3,
          d: 4
        },
        foo: 'my-foo',
        bar: 'my-bar',
      }
    })
2、列表渲染,
  (1)默认数组的当前项的下标变量名默认为index,数组当前项的变量名默认为item
    <view wx:for="{{array}}">
      {{index}}: {{item.message}}
    </view>
  (2)使用wx:for-item可以指定数组当前元素的变量名,使用wx:for-index可以指定数组当前下标的变量名:
    <view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
      {{idx}}: {{itemName.message}}
    </view>
  (3)wx:for也可以嵌套,下边是一个九九乘法表
    <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="i">
      <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j">
        <view wx:if="{{i <= j}}">
          {{i}} * {{j}} = {{i * j}}
        </view>
      </view>
    </view>
  (4)block wx:for,渲染一个包含多节点的结构块
    <block wx:for="{{[1, 2, 3]}}">
      <view> {{index}}: </view>
      <view> {{item}} </view>
    </block>
  (5)数据
    Page({
      data: {
        array: [{
          message: 'foo',
        }, {
          message: 'bar'
        }]
      }
    })
  (6)wx:key的值以两种形式提供
    A、字符串,代表在for循环的array中item的某个property,该property的值需要是列表中唯一的字符串或数字,且不能动态改变
    B、保留关键字*this,代表在for循环中的item本身,这种表示需要item本身是一个唯一的字符串或者数字
      <switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch>
      <button bindtap="switch"> Switch </button>
      <button bindtap="addToFront"> Add to the front </button>
      <switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} </switch>
      <button bindtap="addNumberToFront"> Add to the front </button>
      Page({
        data: {
          objectArray: [
            {id: 5, unique: 'unique_5'},
            {id: 4, unique: 'unique_4'},
            {id: 3, unique: 'unique_3'},
            {id: 2, unique: 'unique_2'},
            {id: 1, unique: 'unique_1'},
            {id: 0, unique: 'unique_0'},
          ],
          numberArray: [1, 2, 3, 4]
        },
        switch: function(e) {
          const length = this.data.objectArray.length
          for (let i = 0; i < length; ++i) {
            const x = Math.floor(Math.random() * length)
            const y = Math.floor(Math.random() * length)
            const temp = this.data.objectArray[x]
            this.data.objectArray[x] = this.data.objectArray[y]
            this.data.objectArray[y] = temp
          }
          this.setData({
            objectArray: this.data.objectArray
          })
        },
        addToFront: function(e) {
          const length = this.data.objectArray.length
          this.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray)
          this.setData({
            objectArray: this.data.objectArray
          })
        },
        addNumberToFront: function(e){
          this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray)
          this.setData({
            numberArray: this.data.numberArray
          })
        }
      })
3、条件渲染
  (1)使用 wx:if="" 来判断是否需要渲染该代码块:
    <view wx:if="{{condition}}"> True </view>
  (2)用 wx:elif 和 wx:else 来添加一个 else 块:
    <view wx:if="{{length > 5}}"> 1 </view>
    <view wx:elif="{{length > 2}}"> 2 </view>
    <view wx:else> 3 </view>
  (3)用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性
    <block wx:if="{{true}}">
      <view> view1 </view>
      <view> view2 </view>
    </block>
    <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性
  (4)if与hidden,wx:if有更高的切换消耗;hidden有更高的初始渲染消耗
4、模板,
  WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用
(1)定义模板
  使用name属性,作为模板的名字。然后在<template/>内定义代码片段,如:
    <!--
      index: int
      msg: string
      time: string
    -->
    <template name="msgItem">
      <view>
        <text> {{index}}: {{msg}} </text>
        <text> Time: {{time}} </text>
      </view>
    </template>
(2)使用模板
  使用is属性,声明需要的使用的模板,然后将模板所需要的data传入
    <template is="msgItem" data="{{...item}}"/>
    Page({
      data: {
        item: {
          index: 0,
          msg: 'this is a template',
          time: '2016-09-15'
        }
      }
    })
(3)is属性可以使用Mustache语法,来动态决定具体需要渲染哪个模板
  <template name="odd">
    <view> odd </view>
  </template>
  <template name="even">
    <view> even </view>
  </template>
  <block wx:for="{{[1, 2, 3, 4, 5]}}">
    <template is="{{item % 2 == 0 ? 'even' : 'odd'}}"/>
  </block>
(4)模板的作用域
  模板拥有自己的作用域,只能使用 data 传入的数据以及模板定义文件中定义的<wxs/>模块
5、引用
  WXML提供两种文件引用方式import和include
  (1)在 item.wxml 中定义了一个叫item的template
    <template name="item">
      <text>{{text}}</text>
    </template>
  (2)在 index.wxml 中引用了 item.wxml,就可以使用item模板
    <import src="item.wxml"/>
    <template is="item" data="{{text: 'forbar'}}"/>
  (3)import的作用域
    import有作用域的概念,只会import目标文件中定义的template,而不会import目标文件import的template
    <!-- A.wxml -->
      <template name="A">
        <text> A template </text>
      </template>
    <!-- B.wxml -->
      <import src="a.wxml"/>
      <template name="B">
        <text> B template </text>
      </template>
    <!-- C.wxml -->
      <import src="b.wxml"/>
      <template is="A"/>  <!-- Error! Can not use tempalte when not import A. -->
      <template is="B"/>
  (4)include
    include,可以将目标文件除了<template/><wxs/>外的整个代码引入,相当于是拷贝到include位置
      <!-- index.wxml -->
        <include src="header.wxml"/>
        <view> body </view>
        <include src="footer.wxml"/>
      <!-- header.wxml -->
        <view> header </view>
      <!-- footer.wxml -->
        <view> footer </view>
 
六、微信小程序-WXS语法参考
1、说明
  (1)WXS是小程序的一套脚本语言,与JavaScript是不同的语言,有自己的语法
  (2)WXS代码可以编写在wxml文件中的<wxs>标签内,或以.wxs为后缀名的文件内
  (3)变量、注释、运算符、语句、数据类型、基础类库,与js类似
2、模块
  (1)每一个.wxs文件和<wxs>标签都是一个单独的模块
  (2)每个模块都有自己独立的作用域,即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见
  (3)一个模块要想对外暴露其内部的私有变量与函数,只能通过module.exports实现
  (4)在微信开发者工具里面,右键可以直接创建.wxs文件,在其中直接编写WXS脚本
3、.wxs文件
  (1)module模块
    A、module对象,每个wxs模块均有一个内置的module对象
    B、exports属性,通过该属性,可以对外共享本模块的私有变量与函数
    /pages/tools.wxs
      var foo = "'hello world' from tools.wxs";
      var bar = function (d) {
        return d;
      }
      module.exports = {
        FOO: foo,
        bar: bar,
      };
      module.exports.msg = "some msg";
    page/index/index.wxml
      <wxs src="./../tools.wxs" module="tools" />
      <view> {{tools.msg}} </view>
      <view> {{tools.bar(tools.FOO)}} </view>
    页面输出
      some msg
      'hello world' from tools.wxs
  (2)require函数
    在.wxs模块中引用其他wxs文件模块,可以使用require函数,引用的时候,要注意如下几点
    A、只能引用.wxs文件模块,且必须使用相对路径
    B、wxs模块均为单例,wxs模块在第一次被引用时,会自动初始化为单例对象;多个页面,多个地方,多次引用,使用的都是同一个wxs模块对象
    C、如果一个wxs模块在定义之后,一直没有被引用,则该模块不会被解析与运行
      /pages/tools.wxs
        var foo = "'hello world' from tools.wxs";
        var bar = function (d) {
          return d;
        }
        module.exports = {
          FOO: foo,
          bar: bar,
        };
        module.exports.msg = "some msg";
      /pages/logic.wxs
        var tools = require("./tools.wxs");
        console.log(tools.FOO);
        console.log(tools.bar("logic.wxs"));
        console.log(tools.msg);
      /page/index/index.wxml -->
        <wxs src="./../logic.wxs" module="logic" />
  (3)<wxs>标签的属性
    A、module属性,是当前<wxs>标签的模块名,  
    B、src属性,可以用来引用其他的wxs文件模块,引用的时候,要注意如下几点
      只能引用.wxs文件模块,且必须使用相对路径
      wxs模块均为单例,wxs模块在第一次被引用时,会自动初始化为单例对象;多个页面,多个地方,多次引用,使用的都是同一个wxs模块对象
      /pages/index/index.js
        Page({
          data: {
            msg: "'hello wrold' from js",
          }
        })
      /pages/index/index.wxml -->
        <wxs src="./../comm.wxs" module="some_comms"></wxs>
      也可以直接使用单标签闭合的写法
        <wxs src="./../comm.wxs" module="some_comms" />
      调用some_comms模块里面的bar函数,且参数为some_comms模块里面的 foo  
        <view>{{some_comms.bar(some_comms.foo)}}</view>
      调用 some_comms 模块里面的bar函数,且参数为page/index/index.js里面的msg 
        <view>{{some_comms.bar(msg)}}</view>
      页面输出:
        'hello world' from comm.wxs
        'hello wrold' from js
      上述例子在文件/page/index/index.wxml中通过<wxs>标签引用了/page/comm.wxs 模块
  (4)注意事项
    A、<wxs>模块只能在定义模块的WXML文件中被访问到,使用<include>或<import>时,<wxs>模块不会被引入到对应的WXML文件中
    B、<template>标签中,只能使用定义该<template>的WXML文件中定义的<wxs>模块
4、引入插件
  var myPluginInterface = requirePlugin('myPlugin');
  myPluginInterface.hello();
 
七、微信小程序-事件系统
  来源,https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html
1、什么是事件
  (1)事件是视图层到逻辑层的通讯方式,(由用户决定执行逻辑和执行时机)
  (2)事件可以将用户的行为反馈到逻辑层进行处理
  (3)事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数
  (4)事件对象可以携带额外信息,如id,dataset,touches
2、事件的使用方式,在组件中绑定一个事件处理函数
  (1)JS绑定
    以下,在index.wxml中,触发点击事件
      <view id="tapTest" data-hi="Weixin" bindtap="tapName"> Click me! </view>
    以下,在index.js中,定义点击函数
      Page({
        tapName: function(event) {
          console.log(event)
        }
      })
  (2)WXS绑定
    以下,在index.wxml中,引入test.wxs脚本,触发点击事件
      <wxs module="wxs" src="./test.wxs"></wxs>
      <view id="tapTest" data-hi="Weixin" bindtap="{{wxs.tapName}}">绑定的WXS函数必须用{{Mustache语法,Mustache胡子}}括起来</view>
    以下,在test.wxs中,定义点击函数
      function tapName(event, ownerInstance) {
        console.log('tap Weixin', JSON.stringify(event))
      }
      module.exports = {
        tapName: tapName
      }
3、事件详解
  (1)冒泡从里向外,先捕获后冒泡
    bind,绑定事件,向上冒泡,后可以紧跟一个冒号,其含义不变,如bind:tap
    mut-bind,绑定事件,向上冒泡,与上级mut-bind“互斥”的,上级mut-bind不会被触发,上级的其它绑定依然会触发
    catch,绑定事件,阻止向上冒泡
  (2)冒泡与阻止冒泡,bindtap与catchtap,点击“inner view”会先后调用handleTap3和handleTap2
    <view id="outer" bindtap="handleTap1">
      “outer view”
      <view id="middle" catchtap="handleTap2">
        “middle view”
        <view id="inner" bindtap="handleTap3">
          “inner view”
        </view>
      </view>
    </view>
  (3)互斥事件,mut-bind,点击“inner view”会先后调用handleTap3和handleTap2,点击“middle view”会调用handleTap2和handleTap1
    <view id="outer" mut-bind:tap="handleTap1">
      “outer view”
      <view id="middle" bindtap="handleTap2">
        “middle view”
        <view id="inner" mut-bind:tap="handleTap3">
          “inner view”
        </view>
      </view>
    </view>
  (4)捕获从外向里,先捕获后冒泡
    capture-bind,捕获
    capture-catch,中断捕获、取消冒泡
  (5)事件的捕获阶段,点击“inner view”会先后调用handleTap2、handleTap4、handleTap3、handleTap1
    <view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
      “outer view”
      <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
        “inner view”
      </view>
    </view>
    如果将上面代码中的第一个capture-bind改为capture-catch,将只触发handleTap2
  (6)事件对象,如无特殊说明,当组件触发事件时,逻辑层绑定该事件的处理函数会收到一个事件对象
    A、BaseEvent 基础事件对象属性列表
      type,代表事件的类型
      timeStamp,页面打开到触发事件所经过的毫秒数
      target,触发事件的源组件
        id,事件源组件的id
        dataset,事件源组件上由data-开头的自定义属性组成的集合
      currentTarget,事件绑定的当前组件
        id,当前组件的id
        dataset,当前组件上由data-开头的自定义属性组成的集合
      mark,识别具体触发事件的target节点,承载一些自定义数据,类似于dataset
        <view mark:myMark="last" bindtap="bindViewTap">
          <button mark:anotherMark="leaf" bindtap="bindButtonTap">按钮</button>
        </view>
        在上述WXML中,如果按钮被点击,将触发bindViewTap和bindButtonTap两个事件,事件携带的event.mark将包含myMark和anotherMark两项
        Page({
          bindViewTap: function(e) {
            e.mark.myMark === "last" //true
            e.mark.anotherMark === "leaf" //true
          }
        })
      //mark,会包含从触发事件的节点到根节点上所有的mark属性值
      //dataset,仅包含一个节点的data-属性值
    B、CustomEvent 自定义事件对象属性列表(继承 BaseEvent)
      detail,额外的信息
    C、TouchEvent 触摸事件对象属性列表(继承 BaseEvent)
      touches,触摸事件,当前停留在屏幕中的触摸点信息的数组,每个元素为一个Touch对象,表示当前停留在屏幕上的触摸点
        identifier,触摸点的标识符
        pageX/pageY,距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴
        clientX/clientY,距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴
      changedTouches,触摸事件,当前变化的触摸点信息的数组
4、WXS响应事件
  (1)以下test.wxml
    <wxs module="test" src="./test.wxs"></wxs>
    <view bindtouchmove="{{test.touchmove}}" change:prop="{{test.propObserver}}" prop="{{propValue}}" class="movable"></view>
    //以上,WXS函数必须用{{}}括起来
    //以上,change:prop(标签上的监听--自悟),属性前面带“change:”前缀,是在prop属性被设置的时候触发WXS函数,类似Component定义的properties里面的observer属性
    //以上,在setData({propValue: newValue})调用之后会触发,而不只是值发生改变,所以在页面初始化的时候会调用一次WxsPropObserver的函数
    //以上,在JS里,可以自动调用WXS,因page()而执行
  (2)以下test.wxs
    module.exports = {
      touchmove: function(event, ownerInstance) {
        //event.instance,表示触发事件的组件的ComponentDescriptor实例
        //ownerInstance,表示的是触发事件的组件所在的组件的ComponentDescriptor实例,如果触发事件的组件是在页面内的,ownerInstance表示的是页面实例
      },
      propObserver: function(newValue, oldValue, ownerInstance, instance) { 
        //ownerInstance,表示的是触发事件的组件所在的组件的ComponentDescriptor实例,如果触发事件的组件是在页面内的,ownerInstance表示的是页面实例
        //instance,表示触发事件的组件的ComponentDescriptor实例
      }
    }
    //以上,instance.callMethod(funcName:string, args:object),WXS调用当前-组件-在逻辑层(App Service)定义的函数
    //以上,ownerInstance.callMethod(funcName:string, args:object),WXS调用当前-页面-在逻辑层(App Service)定义的函数
    //以上,在WXS里,可以手动调用JS
 
八、微信小程序-组件,基础组件
 来源,https://developers.weixin.qq.com/miniprogram/dev/component/
 附、<block><block/>,不是组件,只是一个包装元素,不会在页面中做任何的渲染,它能够设置iffor这些控制属性,设置class、id不会生效
1、视图容器
(1)cover-view,覆盖在原生组件之上的文本视图
  <view class="page-section page-section-gap">
    <map
      style="width: 100%; height: 300px;"
      latitude="{{latitude}}"
      longitude="{{longitude}}"
    >
      <cover-view class="cover-view">
        <cover-view class="container">
          <cover-view class="flex-wrp" style="flex-direction:row;">
            <cover-view class="flex-item demo-text-1"></cover-view>
            <cover-view class="flex-item demo-text-2"></cover-view>
            <cover-view class="flex-item demo-text-3"></cover-view>
          </cover-view>
        </cover-view>
      </cover-view>
    </map>
  </view>
(2)match-media,匹配检测节点
  <match-media min-width="300" max-width="600">
    <view>当页面宽度在 300 ~ 500 px 之间时展示这里</view>
  </match-media>
(3)movable-area,可移动的视图容器,在页面中可以拖拽滑动
  <movable-area>
    <movable-view x="{{x}}" y="{{y}}" direction="all">text</movable-view>
  </movable-area>
(4)scroll-view,可滚动视图区域。类似于轮播图,像素级滑动
  <scroll-view scroll-y="true" style="height: 300rpx;" bindscrolltoupper="upper" bindscrolltolower="lower"
    bindscroll="scroll" scroll-into-view="{{toView}}" scroll-top="{{scrollTop}}">
    <view id="demo1" class="scroll-view-item demo-text-1"></view>
    <view id="demo2"  class="scroll-view-item demo-text-2"></view>
    <view id="demo3" class="scroll-view-item demo-text-3"></view>
  </scroll-view>
(5)swiper,滑块视图容器,swiper-item,仅可放置在swiper组件中,宽高自动设置为100%。类似于轮播图,块级滑动
  <swiper indicator-dots="{{indicatorDots}}"  autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}">
    <block wx:for="{{background}}" wx:key="*this">
      <swiper-item>
        <view class="swiper-item {{item}}"></view>
      </swiper-item>
    </block>
  </swiper>
(6)view,视图容器
  <view class="container">
    <view class="page-body">
      <view class="page-section">
        <view class="page-section-title">
          <text>flex-direction: row\n横向布局</text>
        </view>
        <view class="page-section-spacing">
          <view class="flex-wrp" style="flex-direction:row;">
            <view class="flex-item demo-text-1"></view>
            <view class="flex-item demo-text-2"></view>
            <view class="flex-item demo-text-3"></view>
          </view>
        </view>
      </view>
      <view class="page-section">
        <view class="page-section-title">
          <text>flex-direction: column\n纵向布局</text>
        </view>
        <view class="flex-wrp" style="flex-direction:column;">
          <view class="flex-item flex-item-V demo-text-1"></view>
          <view class="flex-item flex-item-V demo-text-2"></view>
          <view class="flex-item flex-item-V demo-text-3"></view>
        </view>
      </view>
    </view>
  </view>
2、基础内容
(1)icon,图标组件
  <view class="icon-box">
    <icon class="icon-box-img" type="success" size="93"></icon>
    <view class="icon-box-ctn">
      <view class="icon-box-title">成功</view>
      <view class="icon-box-desc">用于表示操作顺利完成</view>
    </view>
  </view>
(2)progress,进度条
  <view class="progress-box">
    <progress percent="20" show-info stroke-width="3"/>
  </view>
(3)rich-text,富文本
  <block wx:if="{{renderedByHtml}}">
    <rich-text nodes="{{htmlSnip}}"></rich-text>
  </block>
  const htmlSnip =
    `<div class="div_class">
      <h1>Title</h1>
      <p class="p">
        Life is <i>like</i> a box of
        <b> chocolates</b>.
      </p>
    </div>
    `
(4)text,文本
  <view class="page-section page-section-spacing">
    <view class="text-box" scroll-y="true" scroll-top="{{scrollTop}}">
      <text>{{text}}</text>
    </view>
    <button disabled="{{!canAdd}}" bindtap="add">add line</button>
    <button disabled="{{!canRemove}}" bindtap="remove">remove line</button>
  </view>
  const texts = [
    '2011年1月,微信1.0发布',
    '同年5月,微信2.0语音对讲发布',
    '10月,微信3.0新增摇一摇功能',
    '2012年3月,微信用户突破1亿',
    '4月份,微信4.0朋友圈发布',
    '同年7月,微信4.2发布公众平台',
    '2013年8月,微信5.0发布微信支付',
    '2014年9月,企业号发布',
    '同月,发布微信卡包',
    '2015年1月,微信第一条朋友圈广告',
    '2016年1月,企业微信发布',
    '2017年1月,小程序发布',
    '......'
  ]
3、表单组件
(1)button,按钮
  <view class="button-sp-area">
    <button type="primary" plain="true">按钮</button>
    <button type="primary" disabled="true" plain="true">不可点击的按钮</button>
  </view>
(2)checkbox,多选项目
  <label class="checkbox">
    <checkbox value="cb" />未选中
  </label>
  <checkbox-group bindchange="checkboxChange">
    <label class="weui-cell weui-check__label" wx:for="{{items}}" wx:key="{{item.value}}">
      <view class="weui-cell__hd">
        <checkbox value="{{item.value}}" checked="{{item.checked}}"/>
      </view>
      <view class="weui-cell__bd">{{item.name}}</view>
    </label>
  </checkbox-group>
(3)checkbox-group,多项选择器,内部由多个checkbox组成,示例见(2)
(4)editor,富文本编辑器,可以对图片、文字进行编辑
  <editor id="editor" read-only="{{false}}" /> //自写
(5)form,表单
  <form catchsubmit="formSubmit" catchreset="formReset">
    <view class="page-section page-section-gap">
      <view class="page-section-title">switch</view>
      <switch name="switch"/>
    </view>
    <view class="btn-area">
      <button style="margin: 30rpx 0" type="primary" formType="submit">Submit</button>
      <button style="margin: 30rpx 0" formType="reset">Reset</button>
    </view>
  </form>
(6)input,输入框
  <view class="weui-cell weui-cell_input">
    <input class="weui-input" auto-focus placeholder="将会获取焦点"/>
  </view>
(7)keyboard-accessory,设置input/textarea聚焦时,键盘上方cover-view/cover-image工具栏视图
  <textarea hold-keyboard="{{true}}">
    <keyboard-accessory class="container" style="height: 50px;">
      <cover-view bindtap="tap" style="flex: 1; background: green;">1</cover-view>
      <cover-view bindtap="tap" style="flex: 1; background: red;">2</cover-view>
    </keyboard-accessory>
  </textarea>
(8)label,用来改进表单组件的可用性
  <checkbox-group class="group" bindchange="checkboxChange">
    <view class="label-1" wx:for="{{checkboxItems}}">
      <label>
        <checkbox value="{{item.name}}" checked="{{item.checked}}"></checkbox>
        <text class="label-1-text">{{item.value}}</text>
      </label>
    </view>
  </checkbox-group>
(9)picker,从底部弹起的滚动选择器
  <picker mode="multiSelector" bindchange="bindMultiPickerChange" bindcolumnchange="bindMultiPickerColumnChange" value="{{multiIndex}}" range="{{multiArray}}">
    <view class="picker">
      当前选择:{{multiArray[0][multiIndex[0]]}},{{multiArray[1][multiIndex[1]]}},{{multiArray[2][multiIndex[2]]}}
    </view>
  </picker>
(10)picker-view,嵌入页面的滚动选择器
  <picker-view indicator-style="height: 50px;" style="width: 100%; height: 300px;" value="{{value}}" bindchange="bindChange">
    <picker-view-column>
      <view wx:for="{{years}}" wx:key="{{years}}" style="line-height: 50px; text-align: center;">{{item}}年</view>
    </picker-view-column>
    <picker-view-column>
      <view wx:for="{{months}}" wx:key="{{months}}" style="line-height: 50px; text-align: center;">{{item}}月</view>
    </picker-view-column>
  </picker-view>
(11)picker-view-column,滚动选择器子项
(12)radio,单选项目
  <radio-group bindchange="radioChange">
    <label class="weui-cell weui-check__label" wx:for="{{items}}" wx:key="{{item.value}}">
      <view class="weui-cell__hd">
        <radio value="{{item.value}}" checked="true"/>
      </view>
      <view class="weui-cell__bd">{{item.name}}</view>
    </label>
  </radio-group>
(13)radio-group,单项选择器,内部由多个radio组成,示例见(12)
(14)slider,滑动选择器
  <view class="body-view">
    <slider bindchange="slider1change" left-icon="cancel" right-icon="success_no_circle"/>
  </view>
(15)switch,开关选择器
  <view class="body-view">
    <switch checked="{{switch1Checked}}" bindchange="switch1Change"/>
  </view>
(16)textarea,多行输入框
  <view class="section">
    <textarea bindblur="bindTextAreaBlur" auto-height placeholder="自动变高" />
  </view>
4、导航
(1)functional-page-navigator,仅在插件中有效,用于跳转到插件功能页
  <functional-page-navigator name="loginAndGetUserInfo" bind:success="loginSuccess">
    <button>登录到插件</button>
  </functional-page-navigator>
(2)navigator,页面链接
  <view class="btn-area">
    <navigator url="/page/navigate/navigate?title=navigate" hover-class="navigator-hover">跳转到新页面</navigator>
    <navigator url="../../redirect/redirect/redirect?title=redirect" open-type="redirect" hover-class="other-navigator-hover">在当前页打开</navigator>
    <navigator url="/page/index/index" open-type="switchTab" hover-class="other-navigator-hover">切换 Tab</navigator>
    <navigator target="miniProgram" open-type="navigate" app-id="" path="" extra-data="" version="release">打开绑定的小程序</navigator>
  </view>
5、媒体组件
(1)camera,系统相机。点击相机图标,调出下面页面。出现人像-拍照人像-预览人像-存储人像
  <camera device-position="back" flash="off" binderror="error" style="width: 100%; height: 300px;"></camera>
  <button type="primary" bindtap="takePhoto">拍照</button>
  <view>预览</view>
  <image mode="widthFix" src="{{src}}"></image>
  Page({
    takePhoto() {
      const ctx = wx.createCameraContext()
      ctx.takePhoto({
        quality: 'high',
        success: (res) => {
          this.setData({
            src: res.tempImagePath
          })
        }
      })
    },
    error(e) {
      console.log(e.detail)
    }
  })
(2)image,图片。mode,图片裁剪、缩放的模式
  <view class="section section_gap" wx:for="{{array}}" wx:for-item="item">
    <view class="section__title">{{item.text}}</view>
    <view class="section__ctn">
      <image style="width: 200px; height: 200px; background-color: #eeeeee;" mode="{{item.mode}}" src="{{src}}"></image>
    </view>
  </view>
(3)live-player,实时音视频播放
  <live-player src="https://domain/pull_stream" mode="RTC" autoplay bindstatechange="statechange" binderror="error" style="width: 300px; height: 225px;" />
(4)live-pusher,实时音视频录制
  <live-pusher url="https://domain/push_stream" mode="RTC" autopush bindstatechange="statechange" style="width: 300px; height: 225px;" />
(5)video,视频
  <video
    id="myVideo"
    src="http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400"
    binderror="videoErrorCallback"
    danmu-list="{{danmuList}}"
    enable-danmu
    danmu-btn
    show-center-play-btn='{{false}}'
    show-play-btn="{{true}}"
    controls
    picture-in-picture-mode="{{['push', 'pop']}}"
    bindenterpictureinpicture='bindVideoEnterPictureInPicture'
    bindleavepictureinpicture='bindVideoLeavePictureInPicture'
  ></video>
(6)voip-room,多人音视频对话
  <block wx:for="{{openIdList}}" wx:key="*this">
    <voip-room
      openid="{{item}}"
      mode="{{selfOpenId === item ? 'camera' : 'video'}}">
    </voip-room>
  </block>
6、地图,https://developers.weixin.qq.com/miniprogram/dev/component/map.html
 
九、微信小程序-自定义组件
  来源,开发-指南-自定义组件
  来源,https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/
1、一个小程序自定义组件由四个文件组成,类似于页面Page
(1).js,自定义组件逻辑
  // page-common-behavior.js
  // module.exports = Behavior({ //https://developers.weixin.qq.com/miniprogram/dev/reference/api/Behavior.html
  //   properties: {}, //组件的对外属性
  //   data: {}, //组件的内部数据
  // })
  var pageCommonBehavior = require('./page-common-behavior')
  Component({
    //来源,https://developers.weixin.qq.com/miniprogram/dev/reference/api/Component.html
    //properties,组件的对外属性,是属性名到属性设置的映射表
    properties: { //properties,组件的对外属性,是属性名到属性设置的映射表
      innerText: {
        type: String,
        value: 'default value',
      }
    },
    //data,组件的内部数据,和properties一同用于组件的模板渲染
    data: {
      someData: {}
    },
    //observers,组件数据字段监听器,用于监听properties和data的变化
    observers: { //组件数据字段监听器,用于监听properties和data的变化;普通监听
      'numberA, numberB': function(numberA, numberB) {//在 numberA或者numberB被设置时,执行这个函数
        this.setData({
          sum: numberA + numberB
        })
      }
    },
    observers: { //监听子数据字段
      'some.subfield': function(subfield) {
        //使用 setData 设置 this.data.some.subfield 时触发
        //(除此以外,使用 setData 设置 this.data.some 也会触发)
        subfield === this.data.some.subfield
      },
      'arr[12]': function(arr12) {
        //使用 setData 设置 this.data.arr[12] 时触发
        //(除此以外,使用 setData 设置 this.data.arr 也会触发)
        arr12 === this.data.arr[12]
      },
    },
    observers: { //监听所有子数据字段的变化,可以使用通配符 **
      'some.field.**': function(field) {
        //使用 setData 设置 this.data.some.field 本身或其下任何子数据字段时触发
        //(除此以外,使用 setData 设置 this.data.some 也会触发)
        field === this.data.some.field
      },
    },
    observers: { //仅使用通配符 ** 可以监听全部 setData
      '**': function() {
        //每次 setData 都触发
      },
    },
    //methods,组件的方法,包括事件响应函数和任意的自定义方法
    methods: {
      customMethod: function(){
        this.setData({ //设置data并执行视图层渲染
          s: false
        })
        this.hasBehavior() //检查组件是否具有behavior(检查时会递归检查被直接或间接引入的所有behavior)
        this.triggerEvent() //触发事件
      }
    },
    //behaviors,组件间可共享的部分,组件间代码复用机制,类似于mixins和traits
    //behaviors,组件引用它时,它的properties、data、method会被合并到组件对应的配置中,生命周期函数也会在对应时机被调用
    behaviors: [pageCommonBehavior],
    behaviors: ['wx://form-field'], //它使得这个自定义组件有类似于表单控件的行为
    //lifetimes,组件生命周期-声明对象,里面的生命周期可以写到外面,但写在这里优先级更高
    lifetimes: {//生命周期函数,可以为函数,或一个在methods段中定义的方法名
      //created,在组件实例刚刚被创建时执行,此时不能调用setData
      created: function() {},
      //attached,在组件实例进入页面节点树时执行,声明的字段会被lifetimes声明的字段覆盖
      attached: function() {
        this.setData({
          numberA: 1,
          numberB: 2,
        })
        this.setData({ //这样会触发上面的 observer
          'some.field': { /* ... */ }
        })
        this.setData({ //这样也会触发上面的 observer
          'some.field.xxx': { /* ... */ }
        })
        this.setData({ //这样还是会触发上面的 observer
          'some': { /* ... */ }
        })
      },
      //ready,组件布局完成后执行
      ready: function() { },
      //moved,组件实例被移动到节点树另一个位置时执行
      moved: function() { },
      //detached,组件实例被从页面节点树移除时执行
      detached: function() { },
    },
    pageLifetimes: {// 组件所在页面的生命周期函数
      show: function () { }, //组件所在的页面被展示时执行
      hide: function () { }, //组件所在的页面被隐藏时执行
      resize(res) { //屏幕旋转事件
        res.size.windowWidth //新的显示区域宽度
        res.size.windowHeight //新的显示区域高度
      }
      routeDone: function () { }, //组件所在页面路由动画完成时执行
    },
    // 组件实例的属性和方法可以在组件的方法、生命周期函数和属性observer中通过this访问
    // 属性名
    //   is,组件的文件路径
    //   id,节点id
    //   dataset,节点dataset
    //   data,组件数据,包括内部数据和属性值
    //   properties,组件数据,包括内部数据和属性值(与data一致)
    //   router,相对于当前自定义组件的Router对象
    //   pageRouter,相对于当前自定义组件所在页面的Router对象
    //   renderer,渲染当前组件的渲染后端
    // 方法名
    //   setData,设置data并执行视图层渲染
    //   hasBehavior,检查组件是否具有behavior(检查时会递归检查被直接或间接引入的所有behavior) 
    //   triggerEvent,触发事件,参见,组件间通信与事件,
    //     https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html
  })
(2).json,自定义组件配置
  {
    "component": true//这一组文件为自定义组件
  }
(3).wxss,自定义组件样式表
  .inner {
    color: red;
  }
(4).wxml,自定义组件结构
  <view class="inner">
    <view>这里是组件的内部节点</view>
    <slot></slot>
  </view>
(5)自定义组件使用
  以下,在页面的.json文件中声明引用
    {
      "usingComponents": {
        "component-tag-name": "path/to/the/custom/component"
      }
    }
  以下,在页面的.wxml文件中使用
    <view>
      <component-tag-name inner-text="Some text">这是插槽内容</component-tag-name>
    </view>
(6)自定义组件扩展
  //提供了修改自定义组件定义段的能力,下面例子就是修改了自定义组件中的data定义段里的内容
  //behavior.js
  module.exports = Behavior({
    definitionFilter(defFields) {
      defFields.data.from = 'behavior'
    },
  })
  //component.js
  Component({
    data: {
      from: 'component'
    },
    behaviors: [require('behavior.js')],
    ready() {
      console.log(this.data.from) //此处会发现输出 behavior 而不是 component
    }
  })
(7)简易双向绑定,自定义组件将自身的myValue属性双向绑定到了组件内输入框的value属性上
  custom-component定义,<input model:value="{{myValue}}" />
  custom-component使用,<custom-component model:my-value="{{pageValue}}" /> 
2、抽象节点,
  有默认渲染内容,使用者决定渲染内容,与插槽相似
(1)自定义组件
  <!-- selectable-group.json -->
  {
    "componentGenerics": {//generic,通用
      "selectable": true
    }
  }
  {
    "componentGenerics": {
      "selectable": {  /* 默认抽象节点 */
        "default": "path/to/default/component"
      }
    }
  }
  <!-- selectable-group.wxml 渲染抽象节点 -->
  <view wx:for="{{labels}}">
    <label>
      <selectable disabled="{{false}}"></selectable>
      {{item}}
    </label>
  </view>
(2)父组件
  <!-- parent.json 定义抽象节点 -->
  {
    "usingComponents": {
      "custom-radio": "path/to/custom/radio",
      "custom-checkbox": "path/to/custom/checkbox"
    }
  }
  <!-- parent.wxml 选择抽象节点 -->
  <selectable-group generic:selectable="custom-radio" />
3、组件间通信与事件
(1)父级
  <!-- 当自定义组件触发“myevent”事件时,调用“onMyEvent”方法 -->
  <component-tag-name bindmyevent="onMyEvent" />
  <!-- 或者可以写成 -->
  <component-tag-name bind:myevent="onMyEvent" />
  Page({
    onMyEvent: function(e){
      e.detail //自定义组件触发事件时提供的detail对象
    }
  })
(2)自身
  <button bindtap="onTap">点击这个按钮将触发“myevent”事件</button>
  Component({
    properties: {},
    methods: {
      onTap: function(){
        var myEventDetail = {} //detail对象,提供给事件监听函数
        var myEventOption = {} //触发事件的选项
        this.triggerEvent('myevent', myEventDetail, myEventOption) //trigger,触发
      }
    }
  })
 
十、微信小程序-API
1、基础
(1)系统
  A、wx.getWindowInfo() //获取窗口信息
  B、wx.getSystemInfo(Object object) // 获取系统信息。是异步的调用格式,但是是同步返回
  C、wx.getDeviceInfo() //获取设备基础信息
  D、wx.getAppBaseInfo() //获取微信APP基础信息
(2)更新
  A、wx.updateWeChatApp(Object object) //更新客户端版本
  B、wx.getUpdateManager() //获取全局唯一的版本更新管理器,用于管理小程序更新
(3)小程序
  A、wx.getApiCategory() //获取当前API类别
  B、wx.onThemeChange(function listener) //监听系统主题改变事件。该事件与App.onThemeChange的回调时机一致
  C、wx.onAppShow(function listener) //监听小程序切前台事件。该事件与App.onShow的回调参数一致
(4)调试
  A、console.log() //向调试面板中打印log日志
  B、console.warn() //向调试面板中打印warn日志
(5)性能
  A、wx.preloadWebview(Object object) //预加载下个页面的WebView
  B、wx.getPerformance() //获取当前小程序性能相关的信息
  C、wx.preloadAssets(Object object) //为视图层预加载媒体资源文件
2、路由
  (1)wx.switchTab(Object object) //跳转到tabBar页面,并关闭其他所有非tabBar页面
  (2)wx.reLaunch(Object object) //关闭所有页面,打开到应用内的某个页面
  (3)wx.redirectTo(Object object) //关闭当前页面,跳转到应用内的某个页面,但是不允许跳转到tabbar页面
  (4)wx.navigateTo(Object object) //保留当前页面,跳转到应用内的某个页面,但是不能跳到tabbar页面,使用wx.navigateBack可以返回到原页面
  (5)wx.navigateBack(Object object) //关闭当前页面,返回上一页面或多级页面。可通过getCurrentPages获取当前的页面栈,决定需要返回几层。
  (6)自定义路由
    A、wx.router //获取router对象
    B、router.addRouteBuilder(string routeType, function routeBuilder) //添加自定义路由配置
      wx.router.addRouteBuilder('slide', slideRouteBuilder) //路由类型,路由动画定义函数
    C、router.getRouteContext(Object this) //获取页面对应的自定义路由上下文对象
    D、router.removeRouteBuilder(string routeType) //移除自定义路由配置
      wx.router.removeRouteBuilder('slide')
3、跳转
  (1)wx.restartMiniProgram(Object object) //重启当前小程序
  (2)wx.openEmbeddedMiniProgram(Object object) //打开半屏小程序
  (3)wx.navigateToMiniProgram(Object object) //打开另一个小程序
  (4)wx.exitMiniProgram(Object object) //退出当前小程序。必须有点击行为才能调用成功
4、转发
  (1)wx.updateShareMenu(Object object) //更新转发属性
  (2)wx.showShareMenu(Object object) //显示当前页面的转发按钮
  (3)wx.shareVideoMessage(Object object) //转发视频到聊天
  (4)wx.shareFileMessage(Object object) //转发文件到聊天
5、界面
(1)交互
  A、wx.showToast(Object object) //显示消息提示框
  B、wx.showModal(Object object) //显示模态对话框
  C、wx.showLoading(Object object) //显示loading提示框。需主动调用wx.hideLoading才能关闭提示框
  D、wx.showActionSheet(Object object) //显示操作菜单
  E、wx.hideToast(Object object) //隐藏消息提示框
  F、wx.hideLoading(Object object) //隐藏loading提示框
(2)导航栏
  A、wx.showNavigationBarLoading(Object object) //在当前页面显示导航条加载动画
  B、wx.setNavigationBarTitle(Object object) //动态设置当前页面的标题
  C、wx.setNavigationBarColor(Object object) //设置页面导航条颜色
  D、wx.hideNavigationBarLoading(Object object) //在当前页面隐藏导航条加载动画
  E、wx.hideHomeButton(Object object) //隐藏返回首页按钮
(3)背景
  A、wx.setBackgroundTextStyle(Object object) //动态设置下拉背景字体、loading图的样式
  B、wx.setBackgroundColor(Object object) //动态设置窗口的背景色
(4)Tab Bar,位于小程序底部的导航栏菜单
  A、wx.showTabBarRedDot(Object object) //显示tabBar某一项的右上角的红点
  B、wx.showTabBar(Object object) //显示tabBar
  C、wx.setTabBarStyle(Object object) //动态设置tabBar的整体样式
  D、wx.setTabBarItem(Object object) //动态设置tabBar某一项的内容
  E、wx.setTabBarBadge(Object object) //为tabBar某一项的右上角添加文本
  F、wx.removeTabBarBadge(Object object) //移除tabBar某一项右上角的文本
  G、wx.hideTabBarRedDot(Object object) //隐藏tabBar某一项的右上角的红点
  H、wx.hideTabBar(Object object) //隐藏tabBar
(5)字体
  A、wx.loadFontFace(Object object) //动态加载网络字体,文件地址需为下载类型。需在app.js中调用
(6)下拉刷新
  A、wx.stopPullDownRefresh(Object object) //停止当前页面下拉刷新
  B、wx.startPullDownRefresh(Object object) //开始下拉刷新。调用后触发下拉刷新动画,效果与用户手动下拉刷新一致。
(7)滚动
  A、wx.pageScrollTo(Object object) //将页面滚动到目标位置,支持选择器和滚动距离两种方式定位
(8)动画
  A、wx.createAnimation(Object object) //创建一个动画实例animation
(9)置顶
  A、wx.setTopBarText(Object object) //动态设置置顶栏文字内容
(10)自定义组件
  A、wx.nextTick(Object object) //延迟一部分操作到下一个时间片再执行。(类似于setTimeout)
(11)菜单
  A、wx.getMenuButtonBoundingClientRect(Object object) //获取菜单按钮(右上角胶囊按钮)的布局位置信息。坐标信息以屏幕左上角为原点。
(12)窗口
  A、wx.setWindowSize(Object object) //设置窗口大小,该接口仅适用于PC平台
  B、wx.onWindowResize(Object object) //窗口尺寸变化事件的监听函数
  C、wx.offWindowResize(Object object) //移除窗口尺寸变化事件的监听函数
  D、wx.checkIsPictureInPictureActive(Object object) //返回当前是否存在小窗播放(小窗在video/live-player/live-pusher下可用)
(13)worklet 动画
  A、wx.worklet(Object object) //获取worklet对象
6、网络
(1)发起请求,wx.request(Object object) //发起HTTPS网络请求
  wx.request({
    url: 'example.php',
    data: {
      x: '',
      y: ''
    },
    header: {
      'content-type': 'application/json' // 默认值
    },
    timeout: 60000, //默认值
    method: 'get', //默认值
    dataType: 'text', //默认值。返回的数据格式,即res.data,返回的数据为JSON时,返回后会对返回的数据进行一次 JSON.parse
    responseType: 'text', //默认值。响应的数据类型,即res,
    enableProfil: true, //是否开启profile,默认开启
    success (res) {
      console.log(res.profile) //网络连接过程中关键时间点的耗时信息
    },
    false (res) {
      console.log(res.errMsg)
    }
  })
(2)wx.downloadFile(Object object) //下载文件资源到本地
  const DownloadTask = wx.downloadFile({
    url: 'https://example.com/audio/123',
    filePath: '指定文件下载后存储的路径(本地路径)',
    enableProfil: true, //是否开启profile,默认开启
    success (res) {
      //只要服务器有响应数据,就会把响应内容写入文件并进入success回调,业务需要自行判断是否下载到了想要的内容
      console.log(res.profile) //网络连接过程中关键时间点的耗时信息
      if(res.statusCode === 200) {
        wx.playVoice({
          filePath: res.tempFilePath
        })
      }
    },
  })
  //DownloadTask.onProgressUpdate(function listener),监听下载进度变化事件
(3)wx.uploadFile(Object object) //将本地资源上传到服务器
  wx.chooseImage({
    success (res) {
      const tempFilePaths = res.tempFilePaths
      const UploadTask = wx.uploadFile({
        url: 'https://example.weixin.qq.com/upload', //仅为示例,非真实的接口地址
        filePath: tempFilePaths[0],
        name: 'file',
        formData: {
          'user': 'test'
        },
        enableProfil: true, //是否开启profile,默认开启
        success (res){
          const data = res.data
          //do something
        }
      })
      //UploadTask.onProgressUpdate(function listener),监听上传进度变化事件
    }
  })
(4)WebSocket //通过WebSocket连接发送数据
  let socketOpen = false
  let socketMsgQueue = []
  wx.connectSocket({
    url: 'test.php'
  })
  wx.onSocketOpen(function(res) {
    socketOpen = true
    for (let i = 0; i < socketMsgQueue.length; i++){
      sendSocketMessage(socketMsgQueue[i])
    }
    socketMsgQueue = []
  })
  function sendSocketMessage(msg) {
    if (socketOpen) {
      wx.sendSocketMessage({
        data:msg
      })
    } else {
      socketMsgQueue.push(msg)
    }
  }
7、支付
  (1)wx.requestVirtualPayment(Object object),发起米大师虚拟支付
  (2)wx.requestPluginPayment(Object object),插件中发起支付
  (3)wx.requestPayment(Object object),发起微信支付
  (4)wx.requestMerchantTransfer(Object object),商家转账用户确认模式下,在微信客户端通过小程序拉起页面请求用户确认收款
    //调用前需在微信支付商户平台/合作伙伴平台-产品中心,申请开通商家转账
  (5)wx.requestCommonPayment(Object object),发起通用支付
8、数据缓存
  (1)wx.setStorageSync(string key, any data) //将数据存储在本地缓存中指定的key中,数据都一直可用
    wx.setStorageSync('key', 'value')
  (2)wx.setStorage(Object object) //将数据存储在本地缓存中指定的key中,数据都一直可用
    wx.setStorage({
      key:"key",
      data:"value"
    })
    wx.setStorage({ //开启加密存储
      key: "key",
      data: "value",
      encrypt: true, //若开启加密存储,setStorage和getStorage需要同时声明encrypt的值为true
      success() {
        wx.getStorage({
          key: "key",
          encrypt: true, //若开启加密存储,setStorage和getStorage需要同时声明encrypt的值为true
          success(res) {
            console.log(res.data)
          }
        })
      }
    })
  (3)wx.getStorageSync(string key) //从本地缓存中同步获取指定key的内容
  (4)wx.getStorage(Object object) //从本地缓存中异步获取指定key的内容
9、数据分析
10、XR-FRAME
11、画布
12、媒体
  (1)地图
    A、wx.createMapContext(string mapId, Object this) //创建map上下文MapContext对象。
      //建议使用“wx.createSelectorQuery”-1,获取context对象。
  (2)图片
    A、wx.saveImageToPhotosAlbum(Object object) //保存图片到系统相册
    B、wx.previewMedia(Object object) //预览图片和视频
    C、wx.previewImage(Object object) //在新页面中全屏预览图片。预览的过程中用户可以进行保存图片、发送给朋友等操作
    D、wx.getImageInfo(Object object) //获取图片信息。网络图片需先配置download域名才能生效
    E、wx.editImage(Object object) //编辑图片接口
    F、wx.cropImage(Object object) //裁剪图片接口
    G、wx.compressImage(Object object) //压缩图片接口,可选压缩质量
    H、wx.chooseMessageFile(Object object) //从客户端会话选择文件
    I、wx.chooseImage(Object object) //从本地相册选择图片或使用相机拍照,请使用wx.chooseMedia代替
  (3)视频
    A、wx.saveVideoToPhotosAlbum(Object object) //保存视频到系统相册。支持mp4视频格式
    B、wx.openVideoEditor(Object object) //打开视频编辑器
    C、wx.getVideoInfo(Object object) //获取视频详细信息
    D、wx.createVideoContext(string id, Object this) //创建video上下文VideoContext对象。
      //建议使用“wx.createSelectorQuery”-1,获取context对象。
    E、wx.compressVideo(Object object) //压缩视频接口
    F、wx.chooseVideo(Object object) //拍摄视频或从手机相册中选视频,请使用wx.chooseMedia代替
    G、wx.chooseMedia(Object object) //拍摄或从手机相册中选择图片或视频
  (4)音频
    A、wx.stopVoice(Object object) //结束播放语音,请使用wx.createInnerAudioContext代替
    B、wx.setInnerAudioOption(Object object) //设置InnerAudioContext的播放选项。设置之后对当前小程序全局生效。
    C、wx.playVoice(Object object) //开始播放语音,请使用wx.createInnerAudioContext代替
    D、wx.pauseVoice(Object object) //暂停正在播放的语音,请使用wx.createInnerAudioContext代替
    E、wx.getAvailableAudioSources(Object object) //获取当前支持的音频输入源
    F、wx.createWebAudioContext() //创建WebAudio上下文
    G、wx.createMediaAudioPlayer() //创建媒体音频播放器对象MediaAudioPlayer对象,可用于播放视频解码器VideoDecoder输出的音频
    H、wx.createInnerAudioContext(Object object) //创建内部audio上下文InnerAudioContext对象
    I、wx.createAudioContext(string id, Object this) //创建audio上下文AudioContext对象,请使用wx.createInnerAudioContext代替
  (5)背景音频
    A、wx.stopBackgroundAudio(Object object) //停止播放音乐,请使用wx.getBackgroundAudioManager代替
    B、wx.seekBackgroundAudio(Object object) //控制音乐播放进度,请使用wx.getBackgroundAudioManager代替
    C、wx.playBackgroundAudio(Object object) //使用后台播放器播放音乐,请使用wx.getBackgroundAudioManager代替
    D、wx.pauseBackgroundAudio(Object object) //暂停播放音乐,请使用wx.getBackgroundAudioManager代替
    E、wx.onBackgroundAudioStop(function listener) //监听音乐停止事件,请使用wx.getBackgroundAudioManager代替
    F、wx.onBackgroundAudioPlay(function listener) //监听音乐播放事件,请使用wx.getBackgroundAudioManager代替
    G、wx.onBackgroundAudioPause(function listener) //监听音乐暂停事件,请使用wx.getBackgroundAudioManager代替
    H、wx.getBackgroundAudioPlayerState(Object object) //获取后台音乐播放状态,请使用wx.getBackgroundAudioManager代替
    I、wx.getBackgroundAudioManager() //获取全局唯一的背景音频管理器
  (6)实时音视频
    A、wx.createLivePusherContext() //创建live-pusher上下文LivePusherContext对象
    B、wx.createLivePlayerContext(string id, Object this) //创建live-player上下文LivePlayerContext对象
      //建议使用“wx.createSelectorQuery”-1,获取context对象
  (7)录音
    A、wx.stopRecord(Object object) //停止录音,请使用wx.getRecorderManager代替
    B、wx.startRecord(Object object) //开始录音,请使用wx.getRecorderManager代替
    C、wx.getRecorderManager() //获取全局唯一的录音管理器RecorderManager
  (8)相机
    A、wx.createCameraContext() //创建camera上下文CameraContext对象
  (9)富文本
      <editor id="editor" /> //自写
      const EditorContext = wx.createSelectorQuery()
      EditorContext.select('#editor')
    A、EditorContext.blur(Object object) //编辑器失焦,同时收起键盘
    B、EditorContext.clear(Object object) //清空编辑器内容
    C、EditorContext.format(string name, string value) //修改样式
    D、EditorContext.getContents(Object object) //获取编辑器内容
    E、EditorContext.getSelectionText(Object object) //获取编辑器已选区域内的纯文本内容
    F、EditorContext.insertDivider(Object object) //插入分割线
    G、EditorContext.insertImage(Object object) //插入图片
    H、EditorContext.insertText(Object object) //覆盖当前选区,设置一段文本
    I、EditorContext.redo(Object object) //恢复
    J、EditorContext.removeFormat(Object object) //清除当前选区的样式
    K、EditorContext.scrollIntoView() //使得编辑器光标处滚动到窗口可视区域内
    L、EditorContext.setContents(Object object) //初始化编辑器内容,html和delta同时存在时仅delta生效
    M、EditorContext.undo(Object object) //撤销
    N、
  (10)音视频合成
    A、wx.createMediaContainer() //创建音视频处理容器,最终可将容器中的轨道合成一个视频
  (11)实时语音,下面接口不完整
    A、wx.updateVoIPChatMuteConfig(Object object) //更新实时语音静音设置
    B、wx.subscribeVoIPVideoMembers(Object object) //订阅视频画面成员
  (12)画面录制器
    A、wx.createMediaRecorder(Object canvas, Object options) //创建WebGL画面录制器,可逐帧录制在WebGL上渲染的画面并导出视频文件
  (13)视频解码器
    A、wx.createVideoDecoder() //创建视频解码器,可逐帧获取解码后的数据
13、位置,下面接口不完整
  (1)wx.stopLocationUpdate(Object object) //关闭监听实时位置变化,前后台都停止消息接收
  (2)wx.startLocationUpdate(Object object) //开启小程序进入前台时接收位置消息
  (3)wx.openLocation(Object object) //使用微信内置地图查看位置
  (4)wx.getLocation(Object object) //获取当前的地理位置、速度
14、文件
  (1)wx.saveFileToDisk(Object object) //保存文件系统的文件到用户磁盘,仅在PC端支持
  (2)wx.openDocument(Object object) //新开页面打开文档
  (3)wx.getFileSystemManager() //获取全局唯一的文件管理器
15、开放接口
  (1)登录
    A、wx.pluginLogin(Object args) //该接口仅在小程序插件中可调用,调用接口获得插件用户标志凭证(code)
    B、wx.login(Object object) //调用接口获取登录凭证(code)
    C、wx.checkSession(Object object) //检查登录态是否过期
  (2)账号信息
    A、wx.getAccountInfoSync() //获取当前账号信息
  (3)用户信息
    A、wx.getUserProfile(Object object) //获取用户信息
    B、wx.getUserInfo(Object object) //获取用户信息
  (4)授权
    A、wx.authorizeForMiniProgram //仅小程序插件中能调用该接口,用法同wx.authorize。目前仅支持三种scope
      wx.authorizeForMiniProgram({
        scope: 'scope.record', //scope.record、scope.writePhotosAlbum、scope.camera
        success () {
          //用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
          wx.startRecord()
        }
      })
    B、wx.authorize //提前向用户发起授权请求
      //可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope
      wx.getSetting({
        success(res) {
          if (!res.authSetting['scope.record']) {
            wx.authorize({
              scope: 'scope.record',
              success () {
                // 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
                wx.startRecord()
              }
            })
          }
        }
      })
  (5)设置
    A、wx.openSetting //功能描述,调起客户端小程序设置界面,返回用户设置的操作结果
      wx.openSetting({
        success (res) {
          console.log(res.authSetting)
          // res.authSetting = {
          //   "scope.userInfo": true,
          //   "scope.userLocation": true
          // }
        }
      })
    B、wx.getSetting //获取用户的当前设置
  (6)收货地址
    A、wx.chooseAddress(Object object) //获取用户收货地址
  (7)卡券
    A、wx.openCard(Object object) //查看微信卡包中的卡券
    B、wx.addCard(Object object) //
  (8)发票
    A、wx.chooseInvoiceTitle(Object object) //选择用户的发票抬头
    B、wx.chooseInvoice(Object object) //选择用户已有的发票
  (9)生物认证
    A、wx.startSoterAuthentication(Object object) //开始SOTER生物认证
    B、wx.checkIsSupportSoterAuthentication(Object object) //获取本机支持的SOTER生物认证方式
    C、wx.checkIsSoterEnrolledInDevice(Object object) //获取设备内是否录入如指纹等生物信息的接口
  (10)微信运动
    A、wx.shareToWeRun(Object object) //分享数据到微信运动
    B、wx.getWeRunData(Object object) //获取用户过去三十一天微信运动步数
  (11)订阅消息
    A、wx.requestSubscribeMessage(Object object) //调起客户端小程序订阅消息界面,返回用户订阅消息的操作结果
    B、wx.requestSubscribeDeviceMessage(Object object) //订阅设备消息接口,调用后弹出授权框,用户同意后会允许开发者给用户发送订阅模版消息
  (12)微信红包
    A、wx.showRedPackage(Object object) //拉取h5领取红包封面页
  (13)收藏
    A、wx.addVideoToFavorites(Object object) //收藏视频
    B、wx.addFileToFavorites(Object object) //收藏文件
  (14)我的小程序
    A、wx.checkIsAddedToMyMiniProgram(Object object) //检查小程序是否被添加至 「我的小程序」
  (15)车牌
    A、wx.chooseLicensePlate(Object object) //选择车牌号
  (16)视频号
    A、wx.reserveChannelsLive(Object object) //预约视频号直播
    B、wx.openChannelsUserProfile(Object object) //打开视频号主页
    C、wx.openChannelsLive(Object object) //打开视频号直播
    D、wx.openChannelsEvent(Object object) //打开视频号活动页
    E、wx.openChannelsActivity(Object object) //打开视频号视频
    F、wx.getChannelsShareKey(Object object) //获取视频号直播卡片/视频卡片的分享来源
    G、wx.getChannelsLiveNoticeInfo(Object object) //获取视频号直播预告信息
    H、wx.getChannelsLiveInfo(Object object) //获取视频号直播信息
  (17)音视频通话
    A、wx.requestDeviceVoIP(Object object) //请求用户授权与设备(组)间进行音视频通话
    B、wx.getDeviceVoIPList(Object object) //查询当前用户授权的音视频通话设备(组)信息
  (18)微信群
    A、wx.getGroupEnterInfo(Object object) //获取微信群聊场景下的小程序启动信息
  (19)隐私信息授权
    A、wx.requirePrivacyAuthorize(Object object) //模拟隐私接口调用,并触发隐私弹窗逻辑
    B、wx.openPrivacyContract(Object object) //跳转至隐私协议页面
    C、wx.onNeedPrivacyAuthorization(function listener) //监听隐私接口需要用户授权事件
    D、wx.getPrivacySetting(Object object) //查询隐私授权情况
  (20)微信客服
    A、wx.openCustomerServiceChat(Object object) //打开微信客服,页面产生点击事件(例如 button 上 bindtap 的回调中)后才可调用
  (21)微信表情
    A、wx.openStickerSetView(Object object) //打开表情专辑
    B、wx.openStickerIPView(Object object) //打开表情IP合辑
    C、wx.openSingleStickerView(Object object) //打开单个表情
16、设备
  (1)蓝牙-通用
  (2)蓝牙-低功耗中心设备
  (3)蓝牙-低功耗外围设备
  (4)蓝牙-信标(Beacon)
  (5)NFC读写
    A、wx.getNFCAdapter() //获取NFC实例
  (6)Wi-Fi(wifi),无线保真(Wireless Fidelity),下面接口不完整
    A、wx.stopWifi(Object object) //关闭wifi模块
    B、wx.startWifi(Object object) //初始化wifi模块
    C、wx.setWifiList(Object object) //设置wifiList中 AP 的相关信息,iOS特有接口
    D、wx.getWifiList(Object object) //请求获取wifi列表
    E、wx.getConnectedWifi(Object object) //获取已连接中的wifi信息
  (7)日历
  (8)联系人
    A、wx.chooseContact(Object object) //拉起手机通讯录,选择联系人
    B、wx.addPhoneContact(Object object) //添加手机通讯录联系人
  (9)无障碍
    A、wx.checkIsOpenAccessibility(Object object) //检测是否开启视觉无障碍功能
  (10)电量
    A、wx.getBatteryInfoSync() //同步获取设备电量
    B、wx.getBatteryInfo(Object object) //获取设备电量
  (11)剪贴板
    A、wx.setClipboardData(Object object) //设置系统剪贴板的内容
    B、wx.getClipboardData(Object object) //获取系统剪贴板的内容
  (12)NFC主机卡模拟
  (13)网络
    A、wx.onNetworkWeakChange(function listener) //监听弱网状态变化事件
    B、wx.onNetworkStatusChange(function listener) //监听网络状态变化事件
    C、wx.offNetworkWeakChange(function listener) //移除弱网状态变化事件的监听函数
    D、wx.offNetworkStatusChange(function listener) //移除网络状态变化事件的监听函数
    E、wx.getNetworkType(Object object) //获取网络类型
    F、wx.getLocalIPAddress(Object object) //
  (14)加密
    A、wx.getRandomValues(Object object) //获取密码学安全随机数
  (15)屏幕
    A、wx.setVisualEffectOnCapture(Object object) //wx.setVisualEffectOnCapture(Object object)
    B、wx.setScreenBrightness(Object object) //设置屏幕亮度
    C、wx.setKeepScreenOn(Object object) //设置是否保持常亮状态
    D、wx.onUserCaptureScreen(function listener) //监听用户主动截屏事件
    E、wx.onScreenRecordingStateChanged(function listener) //监听用户录屏事件
    F、wx.offUserCaptureScreen(function callback) //取消监听用户主动截屏事件
    G、wx.offScreenRecordingStateChanged(function listener) //移除用户录屏事件的监听函数
    H、wx.getScreenRecordingState(Object object) //查询用户是否在录屏
    I、wx.getScreenBrightness(Object object) //获取屏幕亮度
  (16)键盘
    A、wx.onKeyboardHeightChange(function listener) //监听键盘高度变化事件
    B、wx.offKeyboardHeightChange(function listener) //移除键盘高度变化事件的监听函数
    C、wx.hideKeyboard(Object object) //在input、textarea等focus拉起键盘之后,手动调用此接口收起键盘
    D、wx.getSelectedTextRange(Object object) //在input、textarea等focus之后,获取输入框的光标位置
  (17)电话
    A、wx.makePhoneCall(Object object) //拨打电话
  (18)加速计,例如摇一摇
    A、wx.stopAccelerometer(Object object) //停止监听加速度数据
    B、wx.startAccelerometer(Object object) //开始监听加速度数据
    C、wx.onAccelerometerChange(function listener) //监听加速度数据事件
    D、wx.offAccelerometerChange(function listener) //移除加速度数据事件的监听函数
  (19)罗盘
    A、wx.stopCompass(Object object) //停止监听罗盘数据
    B、wx.startCompass(Object object) //开始监听罗盘数据
    C、wx.onCompassChange(function listener) //罗盘数据变化事件的监听函数
    D、wx.offCompassChange(function listener) //移除罗盘数据变化事件的监听函数
  (20)设备方向
    A、wx.stopDeviceMotionListening(Object object) //停止监听设备方向的变化
    B、wx.startDeviceMotionListening(Object object) //开始监听设备方向的变化
    C、wx.onDeviceMotionChange(function listener) //监听设备方向变化事件
    D、wx.offDeviceMotionChange(function listener) //移除设备方向变化事件的监听函数
  (21)陀螺仪,测量偏转、倾斜时的转动角速度
    A、wx.stopGyroscope(Object object) //停止监听陀螺仪数据
    B、wx.startGyroscope(Object object) //开始监听陀螺仪数据
    C、wx.onGyroscopeChange(function listener) //监听陀螺仪数据变化事件
    D、wx.offGyroscopeChange(function listener) //移除陀螺仪数据变化事件的监听函数
  (22)内存
    A、wx.onMemoryWarning(function listener) //监听内存不足告警事件
    B、wx.offMemoryWarning(function listener) //移除内存不足告警事件的监听函数
  (23)扫码
    A、wx.scanCode(Object object) //调起客户端扫码界面进行扫码
  (24)短信
    A、wx.sendSms(Object object) //拉起手机发送短信界面
  (25)振动
    A、wx.vibrateShort(Object object) //使手机发生较短时间的振动(15 ms)
    B、wx.vibrateLong(Object object) //使手机发生较长时间的振动(400 ms)
17、AI
  (1)AI推理
    A、wx.getInferenceEnvInfo(Object object) //获取通用AI推理引擎版本
    B、wx.createInferenceSession(Object object) //创建AI推理Session
  (2)视觉算法
    A、wx.isVKSupport(string version) //判断支持版本
    B、wx.createVKSession(Object object) //创建vision kit会话对象
  (3)人脸检测
    A、wx.stopFaceDetect(Object object) //停止人脸检测。本接口不再维护,请使用wx.createVKSession接口代替
    B、wx.initFaceDetect(Object object) //初始化人脸检测。本接口不再维护,请使用wx.createVKSession接口代替
    C、wx.faceDetect(Object object) //人脸检测。本接口不再维护,请使用wx.createVKSession接口代替
18、Worker
  function createNewWorker() {
    const worker = wx.createWorker('workers/index.js', { //创建一个Worker线程
      useExperimentalWorker: true
    })
    //监听worker被系统回收事件
    worker.onProcessKilled(() => {
      //重新创建一个worker
      createNewWorker()
    })
  }
  //创建实验worker
  createNewWorker()
19、WXML
  const query = wx.createSelectorQuery()
    //返回一个SelectorQuery对象实例。在自定义组件或包含自定义组件的页面中,应使用this.createSelectorQuery()来代替
  query.select('#the-id').boundingClientRect()
  query.selectViewport().scrollOffset()
  query.exec(function(res){
    res[0].top //#the-id节点的上边界坐标
    res[1].scrollTop //显示区域的竖直滚动位置
  })
20、第三方平台
21、广告
22、Skyline
 
十一、uniapp跨端框架-简介
来源,https://gitee.com/dcloud/uni-app/tags?page=60
来源,https://uniapp.dcloud.net.cn/history.html
来源,https://uniapp.dcloud.net.cn/tutorial/
1、uni-app的产生背景
  注、Dcloud一般指数字天堂(北京)网络技术有限公司,2012年04月登记成立,法定代表人王安;来源,百度百科“Dcloud”
  (1)2011年1月,微信1.0发布
  (2)2012年,DCloud开始研发小程序技术,推出了HBuilder开发工具
  (3)2015年,DCloud商用了小程序技术,命名“流应用”,并将该技术标准捐给工信部,同时推进各家流量巨头接入该标准,
    众多开发者用该标准为“流应用”平台提供应用,供用户下载
  (4)2015年9月,DCloud推进微信团队开展小程序业务
  (5)2016年初,微信团队决定上线微信小程序业务,订制了自己的标准,随后包括手机厂商在内的各大流量巨头,
    陆续上线类似微信小程序的业务
  (6)2017年1月,微信小程序发布,微信开发工具开发的微信小程序只能在微信上运行,
    来源,https://developers.weixin.qq.com/miniprogram/dev/component/text.html
  (7)2018年8月,DCloud发布uni-app1.0,为开发者抹平各平台的差异,让一套代码在各APP(应用)上运行,
    开发工具为HBuilder,js框架为vue,DCloud由标准的提供者转为标准的汇总者
2、uni-app的版本发布
  (1)2018年8月,uni-app1.0.0 版本发布,
  (2)2021年9月,uni-app2.0.0 版本发布,
  (3)2023年1月,uni-app3.0.0 版本发布,
3、uni-app与weex[wi:ks]、mpvue功能类似,通过单一代码库构建iOS、Android、Web(H5)和小程序等多个平台的应用
  (1)2016年4月,阿里巴巴发布跨平台移动开发工具weex,开发者将Weex的SDK嵌入自己的APP,解决了频繁发版和多端研发两大问题
  (2)uni-app的vue页面,用“WebKit的”webview渲染,WebKit是一个开源的浏览器引擎
  (3)uni-app的nvue页面,用“基于weex改进的”原生渲染引擎渲染,nvue是“native vue”的缩写,意为“原生vue”
  (4)原生渲染引擎,不是封装别人现成的渲染引擎,而是自己开发的渲染引擎
  (5)自悟,浏览器与APP,前者可以浏览所有网站,后者只能浏览一个网站
4、Hybrid,混合开发
  (1)Native App,一般指原生应用,是一个完整的应用,依托于操作系统,交互性强,拓展性强,需要用户下载安装使用
  (2)Web App,一般指H5应用,使用Web技术(如HTML、CSS和JavaScript)来创建应用程序的用户界面
  (3)Hybrid App,一般是指混合型App,带有原生应用外壳的Web应用,是最多的移动端开发方式
    A、底层依赖于Native提供的容器(WebView),上层使用html&css&JS做业务开发
    B、既有前者良好用户体验的优势,又有后者使用HTML5跨平台开发低成本的优势
5、uni-app与hybrid的区别
  (1)uni-app,用于移动端,后出现,负责-前后端分离-的前端
  (2)hybrid,用于移动端,先出现,负责-前后端混合-的全部
 
十二、uniapp跨端框架-教程
1、uni-app的开发规范
  (1)页面文件遵循Vue单文件组件(SFC)规范,即每个页面是一个.vue文件
  (2)组件标签靠近小程序规范,
  (3)接口能力靠近小程序规范,但需将前缀wx、my等替换为uni
  (4)数据绑定及事件处理同Vue.js规范,同时补充了应用生命周期及页面的生命周期
  (5)如需兼容app-nvue平台,建议使用flex布局进行开发
  (6)uni-app分编译器和运行时(runtime),都内置在HBuilderX中,编译器在开发环境编译代码并生成输出物,
    在各终端上,各运行时(runtime)解析各输出物
2、uni-app的编译器
  (1)编译器,运行在电脑开发环境
  (2)开发者按uni-app规范编写代码,由编译器将开发者的统一代码编译生成每个平台支持的特有代码
    在web平台,将.vue文件编译为js代码
    在微信小程序平台,编译器将.vue文件拆分生成wxml、wxss、js等代码
    在app平台,将.vue文件编译为js代码
    在Android平台,将.uts文件编译为kotlin代码
    在iOS平台,将.uts文件编译为swift代码
  (3)uni-app项目根据所依赖的Vue版本不同,编译器的实现也不同
    vue2版,基于webpack实现
    vue3版,基于Vite实现,性能更快
  (4)支持条件编译
  (5)编译到任意平台时,
    static目录下满足编译条件的文件,会直接复制到最终的打包目录
    static目录下的文件(vue、js、css等)只有被引用时,才会被打包编译
  (6).uts,意为统一类型脚本,全称为“uni type script”
3、uni-app的运行时(runtime)
  (1)runtime,运行在终端上,动态处理数据绑定、事件代理,保证Vue和平台宿主数据的一致性,这是一个比较庞大的工程
    在小程序端,uni-app的runtime,主要是一个小程序版的vue runtime,页面路由、组件、api等方面基本都是转义
    在web端,uni-app的runtime相比普通的vue项目,多了一套ui库、页面路由框架、和uni对象(即常见API封装)
    在App端,uni-app的runtime更复杂,DCloud也有一套小程序引擎,打包app时将开发者的代码和DCloud的小程序打包成了apk或ipa
  (2)uni-app的runtime包括3部分,基础框架、组件、API
4、uni-app处理各终端的逻辑层和视图层分离
  (1)在web平台,逻辑层(js)和视图层(html、css),都运行在统一的webview里
  (2)在小程序和app端,逻辑层和视图层被分离了,原因为基于webview的app因js运算和界面渲染抢资源导致卡顿而性能不佳
    逻辑层都独立成单独的js引擎,不支持浏览器专用的window、dom等API,
    视图层仍然是webview,能视图层操作window、dom
5、uni-app的工程,一个uni-app工程,就是一个“Vue项目”(非常重要),可以通过HBuilderX或cli快速创建 
6、页面
  (1)一个页面就是一个符合Vue SFC规范的.vue文件或.nvue文件
  (2)页面保存在工程根目录下的pages目录下
  (3)每次新建页面,均需在工程根目录下的pages.json中配置pages列表
  (4)删除页面时,需删除.vue文件或.nvue文件,删除pages.json中pages列表项中的配置
  (5)uni-app会将pages.json中pages配置项中的第一个页面,作为当前工程的首页(启动页)
  (6)uni-app页面除支持Vue组件生命周期外还支持页面生命周期函数onInit、onLoad、onShow、onReady、onHide、onUnload、onResize、.........
  (7)uni-app组件支持的生命周期,与vue标准组件的生命周期相同beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
  (8)页面调用接口
    getApp,函数用于获取当前应用实例,一般用于获取全局数据
      const app = getApp()
      console.log(app.globalData)
    getCurrentPages,函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面
      const page = getCurrentPages()
      page.$getAppWebview(),获取当前页面的webview对象实例
      page.route,获取当前页面的路由 
    $getAppWebview(),在getCurrentPages()获得的页面里内置了一个方法$getAppWebview(),获取当前页面的webview对象实例
      var pages = getCurrentPages();
      var page = pages[pages.length - 1];
      var currentWebview = page.$getAppWebview();
      console.log(currentWebview.id);//获得当前webview的id
      console.log(currentWebview.isVisible());//查询当前webview是否可见
  (9)页面通讯
    uni.$emit(eventName,OBJECT),触发全局的自定义事件,附加参数都会传给监听器回调
    uni.$on(eventName,callback),监听全局的自定义事件,事件可以由 uni.$emit 触发,回调函数会接收所有传入事件触发函数的额外参数
    uni.$once(eventName,callback),监听全局的自定义事件,事件可以由 uni.$emit 触发,但是只触发一次,在第一次触发之后移除监听器
    uni.$off([eventName,callback]),移除全局自定义事件监听器
  (10)uni-app框架统一管理页面路由,开发者需要在pages.json里配置每个路由页面的路径及页面样式,使用navigator组件跳转、调用API跳转
  (11)框架以栈的形式管理当前所有页面
  (12)支持在template模板中嵌套<template/>和<block/>
  (13)nvue开发与vue开发的常见区别
7、组件
  (1)uni-app组件
    视图容器
    基础内容
    表单组件
    路由与页面跳转
    媒体组件
  (2)Vue组件
  (3)NVUE组件
  (4)小程序组件
  (5)扩展组件(uni-ui)
8、引用组件
  (1)传统vue项目开发,引用组件需要导入-注册-使用三个步骤,如下:
    <template>
      <view>
        <!-- 3.使用组件 -->
        <uni-rate text="1"></uni-rate>
      </view>
    </template>
    <script>
      //1. 导入组件
      import uniRate from '@/components/uni-rate/uni-rate.vue';
      export default {
        components: { uniRate } //2. 注册组件
      }
    </script>
  (2)Vue 3.x增加了script setup特性,将三步优化为两步,无需注册步骤,更为简洁:
    <template>
      <view>
        <!-- 2.使用组件 -->
        <uni-rate text="1"></uni-rate>
      </view>
    </template>
    <script setup>
      //1. 导入组件
      import uniRate from '@/components/uni-rate/uni-rate.vue';
    </script>
  (3)uni-app的easycom机制,将组件引用进一步优化,开发者只管使用,无需考虑导入和注册,更为高效:
    在 uni-app 项目中,页面引用组件和组件引用组件的方式都是一样的(可以理解为:页面是一种特殊的组件),均支持通过 easycom 方式直接引用。
    <template>
      <view>
        <!-- 1.使用组件 -->
        <uni-rate text="1"></uni-rate>
      </view>
    </template>
    <script>
    </script>
9、引用JS
  (1)绝对路径,@指向项目根目录,在cli项目中@指向src目录
    import add from '@/common/add.js';
  (2)相对路径
    import add from '../../common/add.js';
  (3)js中引入npm包
    import package from 'packageName'
    const package = require('packageName')
10、引用CSS
  <style>
    @import "../../common/uni.css";
    .uni-card {
        box-shadow: none;
    }
  </style> 
11、引用静态资源,https://uniapp.dcloud.net.cn/tutorial/page-static-assets.html
  (1)#模板内引入静态资源
    template内引入静态资源,如image、video等标签的src属性时,可以使用相对路径或者绝对路径
    <!-- 绝对路径,/static指根目录下的static目录,在cli项目中/static指src目录下的static目录 -->
    <image class="logo" src="/static/logo.png"></image>
    <image class="logo" src="@/static/logo.png"></image>
    <!-- 相对路径 -->
    <image class="logo" src="../../static/logo.png"></image>
  (2)css 引入静态资源
    css文件或style标签内引入css文件时(scss、less 文件同理),可以使用相对路径或绝对路径
    /* 绝对路径 */
    @import url('/common/uni.css');
    @import url('@/common/uni.css');
    /* 相对路径 */
    @import url('../../common/uni.css');
12、JS语法
  (1)uni-app的js API由标准ES的js API和uni扩展API这两部分组成
    标准ECMAScript的js仅是最基础的js
    浏览器扩展了window、document、navigator等对象
    小程序扩展了各种wx.xx、my.xx、swan.xx的API
    node扩展了fs等模块
    uni-app扩展了uni对象,并且API命名与小程序保持兼容
  (2)标准js和浏览器js的区别
    h5端,JS运行于浏览器中
    非h5端(包含小程序和App),Android平台JS运行在v8引擎中,iOS平台JS运行在iOS自带的jscore引擎中,都没有运行在浏览器或webview里
    非H5端,虽然不支持window、document、navigator等浏览器的js API,但也支持标准ECMAScript
  (3)支持绝大部分ES6 API的同时,也支持了ES7的 await/async
13、CSS语法
  (1)uni-app的css与web的css基本一致
  (2)nvue页面里的样式比web页面里的样式限制更多
  (3)支持的通用css单位包括px、rpx
14、vue语法,仅以“组合式API”为例
  (1)目前uni-app基于Vue2.6,组合式API由@vue/composition-api支持,setup由unplugin-vue2-script-setup支持
  (2)在main.js或main.ts文件内增加安装@vue/composition-api插件
  (3)在每个nvue页面安装@vue/composition-api插件
15、vue3组合式API(Composition API),按照逻辑关注点,对部分代码进行分组
    注,来自于文章10,https://www.cnblogs.com/gushixianqiancheng/p/13392540.html
  (1)vue2中,通过配置项(data、computed、methods、watch)将相关逻辑拆散,不便于组件阅读和维护
  (2)vue3中,通过组合式API(setup、ref、reactive、watchEffect、watch、computed、toRefs、生命周期的hooks),将相关逻辑写在一起,便于组件阅读和维护
  (3)setup函数接受两个参数:(props、context)
    props参数是响应式数据,解构props的操作必须通过toRefs完成,toRefs将对象的多个属性变成响应式数据,如var {title} = toRefs(props)
    context参数不是响应式数据,可以直接解构,包含attrs、slots、emit,其中attrs是组件的props配置中没有声明的属性
  (4)setup执行时,组件实例尚未被创建,this修改成undefined
  (5)setup之ref和reactive的区别
    ref定义基本类型数据,使用Object.defineProperty实现数据代理,使用refData.value.name获取数据(template模板中不需要.value)
    reactive定义引用类型数据,使用Proxy实现数据代理,使用reactData.username获取数据
  (6)setup通过ref、reactive、computed生成组件所需值;通过方法,改变组件值、全局值
    以下,组合式API之computed,来源,https://blog.csdn.net/ct5211314/article/details/125874348
    <template>
      <div>
        <div>姓:<input type="text" v-model="per.surname"></div>
        <div>名:<input type="text" v-model="per.name"></div>
        <div>姓名:<input type="text" v-model="per.fullName"></div>
      </div>
    </template>
    <script>
    import { computed, reactive } from 'vue'
    export default {
      setup(){
        let per = reactive({
          surname:'勇敢',
          name:'小陈'
        })
        per.fullName = computed(()=>{
          return per.surname+'~'+per.name
        })
        return{
          per
        }
      }
    }
    </script>
    以下,组合式API之watchEffect,来源,https://blog.csdn.net/ZYS10000/article/details/124535467
    watchEffect,是一个帧听器,是一个副作用函数,它会监听引用数据类型的所有属性,不需要具体到某个属性,一旦运行就会立即监听,组件卸载的时候会停止监听。
    import { reactive, watchEffect } from 'vue';
    export default {
      setup(){
        let obj = reactive({
          name:'zs'
        });
        watchEffect(() => {
          console.log('name:',obj.name)
        })
        return {
          obj
        }
      }
    }
16、ts语法
  <script lang="ts">
    //这里编写ts代码
    let s:string = "123"
    console.log(s)
  </script>
17、uts语法
  (1)uts,全称uni type script,是一门跨平台的、高性能的、强类型的现代编程语言,
  (2)uts采用了与ts基本一致的语法规范,支持绝大部分ES6 API
  (3)uts可以被编译为不同平台的编程语言
    web平台,编译为JavaScript
    Android平台,编译为Kotlin
    iOS平台,编译Swift
 
十三、uniapp跨端框架-全局文件
1、pages.json 页面路由,对uni-app进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等
  {
    "pages": [{
      "path": "pages/component/index",
      "style": {
        "navigationBarTitleText": "组件"
      }
    }, {
      "path": "pages/API/index",
      "style": {
        "navigationBarTitleText": "接口"
      }
    }, {
      "path": "pages/component/view/index",
      "style": {
        "navigationBarTitleText": "view"
      }
    }],
    "condition": { //模式配置,仅开发期间生效
      "current": 0, //当前激活的模式(list 的索引项)
      "list": [{
        "name": "test", //模式名称
        "path": "pages/component/view/index" //启动页面,必选
      }]
    },
    "globalStyle": {
      "navigationBarTextStyle": "black",
      "navigationBarTitleText": "演示",
      "navigationBarBackgroundColor": "#F8F8F8",
      "backgroundColor": "#F8F8F8",
      "usingComponents":{
        "collapse-tree-item":"/components/collapse-tree-item"
      },
      "renderingMode": "seperated", //仅微信小程序,webrtc 无法正常时尝试强制关闭同层渲染
      "pageOrientation": "portrait", //横屏配置,全局屏幕旋转设置(仅 APP/微信/QQ小程序),支持 auto / portrait / landscape
      "rpxCalcMaxDeviceWidth": 960,
      "rpxCalcBaseDeviceWidth": 375,
      "rpxCalcIncludeWidth": 750
    },
    "tabBar": {
      "color": "#7A7E83",
      "selectedColor": "#3cc51f",
      "borderStyle": "black",
      "backgroundColor": "#ffffff",
      "height": "50px",
      "fontSize": "10px",
      "iconWidth": "24px",
      "spacing": "3px",
        "iconfontSrc":"static/iconfont.ttf", //app tabbar 字体.ttf文件路径 app 3.4.4+
      "list": [{
        "pagePath": "pages/component/index",
        "iconPath": "static/image/icon_component.png",
        "selectedIconPath": "static/image/icon_component_HL.png",
        "text": "组件",
            "iconfont": { //优先级高于 iconPath,该属性依赖 tabbar 根节点的 iconfontSrc
              "text": "\ue102",
              "selectedText": "\ue103",
              "fontSize": "17px",
              "color": "#000000",
              "selectedColor": "#0000ff"
            }
      }, {
        "pagePath": "pages/API/index",
        "iconPath": "static/image/icon_API.png",
        "selectedIconPath": "static/image/icon_API_HL.png",
        "text": "接口"
      }],
      "midButton": {
        "width": "80px",
        "height": "50px",
        "text": "文字",
        "iconPath": "static/image/midButton_iconPath.png",
        "iconWidth": "24px",
        "backgroundImage": "static/image/midButton_backgroundImage.png"
      }
    },
    "easycom": {
      "autoscan": true, //是否自动扫描组件
      "custom": {//自定义扫描规则
        "^uni-(.*)": "@/components/uni-$1.vue"
      }
    },
    "topWindow": {
      "path": "responsive/top-window.vue",
      "style": {
        "height": "44px"
      }
    },
    "leftWindow": {
      "path": "responsive/left-window.vue",
      "style": {
        "width": "300px"
      }
    },
    "rightWindow": {
      "path": "responsive/right-window.vue",
      "style": {
        "width": "300px"
      },
      "matchMedia": {
        "minWidth": 768
      }
    }
  }
2、manifest.json配置,文件是应用的配置文件,用于指定应用的名称、图标、权限等
  {
    "quickapp-webview": {//快应用通用配置
      "icon": "/static/logo.png",
      "package": "com.example.demo",
      "versionName": "1.0.0",
      "versionCode": 100
    },
    "quickapp-webview-union": {//快应用联盟,目前仅支持 vivo、oppo
      "minPlatformVersion": 1063 //最小平台支持
    },
    "quickapp-webview-huawei": {//快应用华为
      "minPlatformVersion": 1070 //最小平台支持
    }
  }
3、package.json扩展配置
  {
    /**
     * package.json其它原有配置
     * 拷贝代码后请去掉注释!
     */
    "uni-app": {//扩展配置
      "scripts": {
        "custom-platform": { //自定义编译平台配置,可通过cli方式调用
          "title":"自定义扩展名称", //在HBuilderX中会显示在 运行/发行 菜单中
          "browser":""//运行到的目标浏览器,仅当UNI_PLATFORM为h5时有效
          "env": {//环境变量
            "UNI_PLATFORM": ""//基准平台
            "MY_TEST": "", //... 其他自定义环境变量
          },
          "define": { //自定义条件编译
            "CUSTOM-CONST": true //自定义条件编译常量,建议为大写
          }
        }
      }   
    }
  }
4、vue.config.js,是一个可选的配置文件,如果项目的根目录中存在这个文件,那么它会被自动加载,一般用于配置webpack等编译选项
  const path = require('path')
  const webpack = require('webpack')
  const CopyWebpackPlugin = require('copy-webpack-plugin') //最新版本copy-webpack-plugin插件暂不兼容,推荐v5.0.0
  module.exports = {
    configureWebpack: {
      plugins: [
        new CopyWebpackPlugin([
          {
            from: path.join(__dirname, 'src/images'),
            to: path.join(__dirname, 'dist', process.env.NODE_ENV === 'production' ? 'build' : 'dev', process.env.UNI_PLATFORM, 'images')
          }
        ])
      ]
    },
    chainWebpack: config => {
      config
        .plugin('define')
        .tap(args => {
          args[0]['process.env'].VUE_APP_TEST = '"test"'
          return args
        })
    }
  }
5、vite.config.js,是一个可选的配置文件,如果项目的根目录中存在这个文件,那么它会被自动加载,一般用于配置vite的编译选项,
  必须引用 '@dcloudio/vite-plugin-uni' 并且添加到 plugins 中
  示例一、自定义静态资源目录
  import path from 'path';
  import fs from 'fs-extra';
  import { defineConfig } from 'vite';
  import uni from '@dcloudio/vite-plugin-uni';
  function copyFile() {
    return {
      enforce: 'post',
      async writeBundle() {
        await fs.copy(
          path.resolve(__dirname, 'images'),
          path.join(
            __dirname,
            'unpackage/dist',
            process.env.NODE_ENV === 'production' ? 'build' : 'dev',
            process.env.UNI_PLATFORM,
            'images'
          )
        );
      },
    };
  }
  export default defineConfig({
    plugins: [uni(), copyFile()],
  });
  示例二、注入全局依赖
  //示例从插件市场下载 mp-storage
  import path from 'path';
  import { defineConfig } from 'vite';
  import uni from '@dcloudio/vite-plugin-uni';
  import inject from '@rollup/plugin-inject';
  const mpStoragePath = path.resolve(__dirname, './js_sdk/mp-storage/mp-storage');
  export default defineConfig({
    plugins: [
      uni(),
      inject({
        localStorage: [mpStoragePath, 'localStorage'],
        'window.localStorage': [mpStoragePath, 'localStorage'],
      }),
    ],
    define: {
      'process.env.VUE_APP_TEST': JSON.stringify('test'),
    },
  });
  示例三、配置环境变量
  import { defineConfig } from 'vite';
  import uni from '@dcloudio/vite-plugin-uni';
  export default defineConfig({
    plugins: [uni()],
    define: {
      'process.env.VUE_APP_TEST': JSON.stringify('test'),
    },
  });
6、uni.scss文件的用途是为了方便整体控制应用的风格。比如按钮颜色、边框风格,uni.scss文件里预置了一批scss变量预置
  <style lang="scss">
  </style>
  以下是uni.scss的相关变量
  $uni-color-primary: #007aff;
  $uni-color-success: #4cd964;
  $uni-color-warning: #f0ad4e;
  $uni-color-error: #dd524d;
7、App.vue是uni-app的主组件,所有页面都是在App.vue下进行切换的,是页面的入口文件
  (1)App.vue本身不是页面,这里不能编写视图元素,也就是没有<template>
  (2)这个文件的作用包括:调用应用生命周期函数、配置全局样式、配置全局的存储globalData
  (3)应用生命周期仅可在App.vue中监听,在页面监听无效
  (4)js中操作globalData的方式如下:getApp().globalData.text = 'test'
  (5)示例代码
    <script>
      //只能在App.vue里监听应用的生命周期
      export default {
        globalData: { 
          text: 'text' 
        }
        onLaunch: function() {
          console.log('App Launch')
        },
        onShow: function() {
          console.log('App Show')
        },
        onHide: function() {
          console.log('App Hide')
        }
      }
    </script>
8、main.js是uni-app的入口文件,主要作用是初始化vue实例、定义全局组件、使用需要的插件如vuex
  (1)vue2代码示例
    import Vue from 'vue'
    import App from './App'
    import pageHead from './components/page-head.vue' //全局引用 page-head 组件
    Vue.config.productionTip = false
    Vue.component('page-head', pageHead) //全局注册 page-head 组件,每个页面将可以直接使用该组件
    App.mpType = 'app'
    const app = new Vue({
      ...App
    })
    app.$mount() //挂载 Vue 实例
  (2)vue3代码示例
    import App from './App'
    import { createSSRApp } from 'vue'
    export function createApp() {
      const app = createSSRApp(App)
      return {
        app
      }
    }
 
十四、postcss.config.js
来源,https://www.fke6.com/html/110797.html
来源,https://blog.csdn.net/Jensen_Yao/article/details/103203490
注、通过gulp、webpack、grunt等构建工具来使用,用于配置PostCSS的插件和选项,处理CSS
1、示例一,插件排序与插件参数
  module.exports = {
    plugins: [//插件排序
      require('postcss-import'),
      require('postcss-url')({//插件参数
        url: 'inline'
      }),
      require('precss'),
      require('autoprefixer')({//插件参数
        browsers: ['last 2 versions']
      })
    ]
  }
2、示例二,px转rem,rootValue*10=设计稿的宽
  module.exports = () => ({
    plugins: [
      require('autoprefixer')(),
      //require('postcss-px2rem')({ remUnit: 75 })
      require('postcss-pxtorem')({
        rootValue: 37.5, //对应设计图宽度375px
        propList: ['*'], //将哪些属性的px值转换,['*']将所有属性的px值转换,['*', '!border*']含border的属性的px值不转换,其余的都转换
      })
    ]
  });
3、示例三,px转vw
  module.exports = {
    plugins: {
      autoprefixer: {},
      'postcss-px-to-viewport': {
        exclude: undefined, //忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
        fontViewportUnit: 'vw', //字体使用的视口单位
        include: undefined, //如果设置了include,那将只有匹配到的文件才会被转换
        landscape: false, //是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
        landscapeUnit: 'vw', //横屏时使用的单位
        landscapeWidth: 1920, //横屏时使用的视口宽度
        mediaQuery: false, //媒体查询里的单位`px`是否需要转换,false为默认值
        minPixelValue: 1, //设置最小的转换数值,只有大于`1px`的值转换为视窗单位
        propList: ['*'], //能转化为vw的属性列表
        replace: true, //是否直接更换属性值,而不添加备用属性
        selectorBlackList: ['p', '.hairlines'], //需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位
        unitPrecision: 5, //转换后保留的小数位数,precision精确
        unitToConvert: 'px', //需要转换的单位,默认为"px"
        viewportWidth: 375, //设计稿的视口宽度,375px=100vw
        viewportHeight: 1334, //视窗的高度,1334px=100vh
        viewportUnit: 'vw', //指定转换后的视窗单位,建议使用vw
      },
      'postcss-viewport-units': {
        //排除会产生警告的部份
        filterRule: rule => rule.nodes.findIndex(i => i.prop === 'content') === -1
      },
      cssnano: {//集成了部分PostCSS插件,用false禁用其中的某个插件,nano毫微
        preset: 'advanced', //预设: 高级(转换)
        autoprefixer: false, //禁用autoprefixer,和上面的autoprefixer: {}具有相同效果
        'postcss-zindex': false
      }
    }
  }
  

  

posted @   WEB前端工程师_钱成  阅读(6761)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示